ZAP Scanning Report

Generated with ZAP on Tue 7 Dec 2021, at 12:23:56

Contents

About this report

Report parameters

Contexts

No contexts were selected, so all contexts were included by default.

Sites

The following sites were included:

  • https://dev.duracloud.org

(If no sites were selected, all sites were included by default.)

An included site must also be within one of the included contexts for its data to be included in the report.

Risk levels

Included: High, Medium, Low, Informational

Excluded: None

Confidence levels

Included: User Confirmed, High, Medium, Low

Excluded: User Confirmed, High, Medium, Low, False Positive

Summaries

Alert counts by risk and confidence

This table shows the number of alerts for each level of risk and confidence included in the report.

(The percentages in brackets represent the count as a percentage of the total number of alerts included in the report, rounded to one decimal place.)

Confidence
User Confirmed High Medium Low Total
Risk High 0
(0.0%)
0
(0.0%)
0
(0.0%)
0
(0.0%)
0
(0.0%)
Medium 0
(0.0%)
0
(0.0%)
37
(32.2%)
0
(0.0%)
37
(32.2%)
Low 0
(0.0%)
0
(0.0%)
34
(29.6%)
7
(6.1%)
41
(35.7%)
Informational 0
(0.0%)
0
(0.0%)
0
(0.0%)
37
(32.2%)
37
(32.2%)
Total 0
(0.0%)
0
(0.0%)
71
(61.7%)
44
(38.3%)
115
(100%)

Alert counts by site and risk

This table shows, for each site for which one or more alerts were raised, the number of alerts raised at each risk level.

Alerts with a confidence level of "False Positive" have been excluded from these counts.

(The numbers in brackets are the number of alerts raised for the site at or above that risk level.)

Risk
High
(= High)
Medium
(>= Medium)
Low
(>= Low)
Informational
(>= Informational)
Site https://dev.duracloud.org 0
(0)
37
(37)
41
(78)
37
(115)

Alert counts by alert type

This table shows the number of alerts of each alert type, together with the alert type's risk level.

(The percentages in brackets represent each count as a percentage, rounded to one decimal place, of the total number of alerts included in this report.)

Alert type Risk Count
Cross-Domain Misconfiguration Medium 36
(31.3%)
Vulnerable JS Library Medium 1
(0.9%)
Absence of Anti-CSRF Tokens Low 4
(3.5%)
Cookie without SameSite Attribute Low 2
(1.7%)
Timestamp Disclosure - Unix Low 7
(6.1%)
X-Content-Type-Options Header Missing Low 28
(24.3%)
Information Disclosure - Suspicious Comments Informational 37
(32.2%)
Total 115

Alerts

  1. Risk=Medium, Confidence=Medium (37)

    1. https://dev.duracloud.org (37)

      1. Cross-Domain Misconfiguration (36)
        1. GET https://dev.duracloud.org
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (239 bytes)
          GET https://dev.duracloud.org HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:52 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=5E31D0F4635FF98D07FB6B0F6D1FBCA9; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        2. GET https://dev.duracloud.org/duradmin
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (284 bytes)
          GET https://dev.duracloud.org/duradmin HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org
          
          
          Request body (0 bytes)
          Response
          Status line and header section (309 bytes)
          HTTP/1.1 302
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Length: 0
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Location: /duradmin/
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (0 bytes)
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        3. GET https://dev.duracloud.org/duradmin/
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (294 bytes)
          GET https://dev.duracloud.org/duradmin/ HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        4. GET https://dev.duracloud.org/duradmin/?error
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (359 bytes)
          GET https://dev.duracloud.org/duradmin/?error HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/login
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (630 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        5. GET https://dev.duracloud.org/duradmin/favicon.ico
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (359 bytes)
          GET https://dev.duracloud.org/duradmin/favicon.ico HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (439 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: image/x-icon
          Content-Length: 1406
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"1406-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (1406 bytes)
          h( ùôîêêêñãÔÛÛÛÿ÷îèæåòå×ÙÙÙòçÚîÝÍöðêçиôéÝòåØùïåþþý±¨ŸòçÛààßüúøõíãÂÂÁûöó÷ïæÛÚØþþþÿþþýúù÷í䤤¤ééèÏÏÏëØÅþþÿòðíøñêìÚȱ³´ùóíÏÏÐðâÓîÞÎçѹøñëãǬú÷óÉÉÉùóîüùöñâÔÿÿþÆÇÇÇÇÇìÛÇýûùéѺñä×÷îäôêßþýüÿýüòæÚüù÷¶¶¶ÿÿÿéÕÀÞ¾žúôíýýý÷ðèõìãäåçöîæ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@!2@@@@@@@@@@@@@@@@@@@@49E=+:0.?3%
          A6)15H.'G"+#E(+!<7C-@;@ 5*F@;@@>	8B/;	
          >@2@@@2@(,$#@22@@@@@@@&@@2@@@@@@@@@@2@@@@@@@@@@@@@2@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        6. GET https://dev.duracloud.org/duradmin/images/logo_top_duracloud_lg.png
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (380 bytes)
          GET https://dev.duracloud.org/duradmin/images/logo_top_duracloud_lg.png HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (438 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: image/png
          Content-Length: 10073
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10073-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10073 bytes)
          ‰PNG
          
          
          IHDR˜<šOsÙtEXtSoftwareAdobe ImageReadyqÉe<&ûIDATxÚì}x\Õµî™Þg$Ê¨KV±dË
          W؎
          ØØÆár“n€Çƒ$/ðø>^ ܄|¹ÀKƒûBnrC(Ø°
          î¶Ü»\$«ºFÓû¼µÖÒ,%l&ŸOû›ÑÌ9»þ{õµG‘H$¤/Ñ¥€¢dE…¯
          ,41(qögß]º.àRIÆI€Ò@ÑBѱW
          MbàŠ@	C	aï£p—®K¢X*‘“	ŠŠ_MdDÁ"*?/¾úðóíEû’ŒX ŠJ;”L|̀bÃï´x$Àä†Ò¥J7”^(.^)Ú%}RS(Ÿ›A\IìP€ËŠ r@)åX«{ÂÎS½»ýYAsêó96½·$ËØ]Sh«›Qž±>j†Ò
          ¥'(ZP€æåK²*«+Î÷ÁÏÀ¸H¡°Š¡”°f¾µ»mnS?í|ë+´{o˜ž·ÀVÿÖCiÒeJ@°Ë/È.lpH•‰%æ`A©zswÛ²µ:j>jÝ×OÍÛ¼ô²Üwàí)(P:‘¿ û¨û¢É`*Æ®	ÿùnýí›\y§âU{ÛçÀ$Çh1ò¹	#„ÿ_º¾¨c¬Ñ„2—`‹Õç.›Qt¤é½yé/}ÖÐéMëù,‰ÍÑÛûœóZ•ÿê	9a¦MƱý
          ýdWãÙÑä×/‹ÜöE£`*49¹+J9°Åë?\có,=·Í.:ž›®,¯5Ä8Ö%Ëp[êzª6ï®lîñ§‹gVîi¿”€¾	E¶8I‹Ï†˜öªdf8jœ,acìË"»}!d0”½hz(lñx›{ñoVŸZ6Òý:2ú/³‹êfWÚw †Èå©aƒ’%ûFmÛìu;&ÉÏ«•‘Ç¿^ó—4“FÈcmhÎ  T¸q	`Q¬7€æ¾«ý<ís/ƒ!HÌ~Eï%\¨“yRY
          )‰QôfmۜÑØá¿Í/­­ÌµpF€ô⇛ӳúúnš‘ï󅢪­u=5¡h\ó̺Ó7?rSõ
          5=c#À<HéúðÕMm
          ŠöE¥fêÏ°hQȕCE•B	ȅ#Ë@ðl”Q
          ÷Y»ëû¦dŠ”ëÿÜ4î}‹A-LÇ¡4IƒFT4ÜxªÄþ*FÆÕè¿^U¼îD»§°Û²µôúí ß]÷Í«Šv[
          š®¦n¿²­?`®ksXTþˆ ~Št“ƫת3Ë3•d™„™£Š_0…Üü¢‚LýOK‹¦³”tᤤ‡,ìA\lb5dU'0}w}ÿˆæˆûUìp탷G‘zurpÁÇè•ÈÊBؾø_û•ñÙ;^ÝѲHÜò].”eç3֍Gºf/´6,›š·€v@Jz_dMTýOD­Èj2ñՊ€£þŐjpÇ»‘²ô#@$— Ý¾ŒÔöónx{íX‚‚`½Ã¨¾	³~ԇÒ° &ûƒ5ûWz‚Qó…Žùh‹{Ìi§·ð«Óó7@=k¥¤ï3Jí}Ѩ˜úŸ.bA&4ˆæ Q4ÿL—¯üƒcÝ3@k+ ö˜€?Z,Î26Ϫ°“m¬M¸lºÍ¦£¼”ìIŸÚæâ)Ž£¬V|Î=¸R›²a¶#;Æ¿qeÑ_Vìi¿©Ã,Ъ•á²sh•§³¬ºî‰E6ÁþT¦¢¦_áñ6OÙI§'›êòRÀ€Œ(r€±èØ(b„”bþH°ÍpI‹L™,
          R¨ViŸ7\ý·ÍM_í¯â\u䥜7ÎÈó0‚%Œ¬µÔÙ¼ò±×ÎI5GühIå?à­ìHƒî÷ùhp)ýM#­©­¿‹IÉ°žAO›§½?Põ×gp¹Pȃ?»eü3é&í.ø·•¤hSvHŒPbþàaD~ž´H%ÊbqÄÎ.é÷…'>ýöÉ;{<¡³ó»¡4?o§+”NßÂå>»îô·®›yè[sŠ7ââêe
          8{,w˜]Hñˆ¥ž·{‡Q±.nŸïAö®f¬ŽØ‚Ñ!¸ßXíý¿ïœœJB¦LÉ"q5Èeó¾6³À‰,Ø+%C…LÑ1àØ´ØE}P¼Z™=dŇdÉ/+‹$wŽ`iÂZúÔªáঐ™]7Ù±'^L˜´Ãê67ÍlFÜ·íDÏDo0šý¯sŠë,úÁ¡ì<Õë8¤†.”Ù>ji±~|
           (ø‚s’Ĩ^AsÛ좠®™T)€­Dtg‘,¨Æþ)X¤ôX¤áaEr/ŽË…uˆÿ«ðYÙ§
          0æŒ6!{ÌûïM7ppM*Në¸÷Ú²õhBè@Pˆ6M/Ëè¯Èµt<½êč]î59Gãr_ڕU™­­½3Q~lÔ*%£Âª­¥ý1FeRít±(5i¹ÖÜt½£8Ó8žX¥xuº‚sÓô*ö‘æȆÑÚÔíÏuº™ŠA’¶ßìµÍ,dúèÆ~ù?+ S
          €’˜ì Æ)À%(MÁÞ3ýè~˜|€ëi0bA˜ÚQÀ–pÂ{ӌšÀ׏M<ýö‰¯u
          „ÄΖ„PÿÎ>gùhý(´ÀÈvváë Т0þÊz½(+v¦ÞóÿÞ­¯ùßËÆF›(~œ'KK¯¿`ÝÁΩ'œž|·?bH}Ö
          sQS`­ûöܒ·˜<H2ZA–øÂµDR5ÌÖ¥Gp‰À¿ÒMǺ¯àÎä¹ã²ÎHƒ®›zY²‰=²è]ÆèŸ\uâfþüH,œw÷.^äSÓ 
          Aõ¸Id9P«Qù="àñߗ›víĜÌñ…6—Y¯nÈ<ÐèÊÔùÃê Û~²wÊéoُ–Vþ7P43V 7*Àò©uՁb‘Ö£GP˜áԌڗ=Æ{(àσÐ^‡ jÇÝÞÃá#ùILP¥ÄÝʔ¿[{êëô¼ˆD]4ÙÑèEÕ+÷´—Á&f”g¬E­‘ü…ŸvjÙ¤ d=Evã™SNï0à
          üÚÎÖ*(©!.<ÿAãm )+™]±‡¢Iy ¥ ŒÀ»è@S_pQr…å‡t”%HXÍDÓD±‰áà’¾:*,¨ÖŸ`¶ Ùº?¾Ð¸az¾´ëTïi&­ï;óJ¶u“…Ý«'äPL}R0اm-KI_d×Ô1éÛ·ÖõL#Eå|.¡ôÀækžQ–Ñ	r\ÌŒªÿkCC—7Å{ fsgWÚÉéßŔr´»‘²y|ÛEõIR0îp¶£Œ%ìEŽ~_8ooCÿض¾@žJ©Ð©UJcŸ7¬çv!—?¬—’NàîºøìÆÃ(ƒ4Í(+q,qfñ'—’ëôJI·Ï§
          °0ö¡³,Ǽ环”þù½CK£±¸95æŒ_ÂV6»2³õ_fnBŠ$€`¶_² &»5U¡ye{s•x­)´fX
          'Ž™F²`'3PKdêO˜z‘b	ÖWºíDÏÜm'z¯¬ïôž«œdJ¨ÂÊÈeäÁ÷~|F'
          Ï
          
          3»Tˆ±‰F&ÙÈ|¤åM)IC ,]¹·½&UIàºoaù¶Ê\Ëô@ôâ¨"ÝîPáHsZ¹ðÃóŊð¢|»ÁyÝäÜ
          ‹äÜÿEM,þ¤(˜R.SøÖî¶ÖèXt¾€Luwi{ñQŒž1fj ن´Ô8³p“`ËÃ|>õhRÖçÛ$úè–MÍë¹ÌrÒéÉ!p=t}Õª»á€”L4qã‹WÍñ6þ|û ØqC§¯èÙu§ïX<%·à«ÓòÞd›/œÊ->˓£€bU§‚KLÚÄ¢´¦r‡¹Å Uyg–gm1š’Øe¸:ߺ_ôº¤d0އ-XŒYÍSYÒg-,™(k‚j=8VYNù±ë¹÷êoíñ†³¿=§ø®ƒ¬6diAàEfw 2¢6,L= 
          ;XدL9t­Þï¼ÆnÖv]Y•IÆY3ß|æ&X¤e큎yüËyã²NÃΩaµ…¹EdÖ5©8-ˆƒìG60p.Y‰çsޒb¨%­’ˈ}°èíßX}PJ†	Ñ|\J›J°·NÁþ±zÇ·@¦Õf˜µAظ] àŸ„9îC0Šglí½º£år.¯­?ÒùØvä8‚ª…|{16å'	°!‡lç@(‹¾r¼ÀµKJ&®öKÉèÑ0#ÕY¼˜$û³4[”Í+%C‚”ÒðÐ$ò>HìÞÎYö E
          ]+%cÊȔ#ÖÂ\aèøђÊ6ØôÓßÜÝ6UTâìæ;v€|W/}6Çg`
          Æ
          BA/-šìX
          àڊ¶-&”†ûîRËǎ
          @cïY_H½#„Éðx>n–‰Dl“|›1¦”Pö…_û˜íBPª˜D÷+‘£ÊÕkÑŽÅ@™˜/nîñ[`½«LÛ'0ò«‘Õ]Ã(’ÍP<;†^ã)þ.š(©*ϲùÆéù+‘bu"õêc¼’µKZ(µ§Æ€Dîë‹IÃ#b#ùژ¿SÅJ*åÀìyºËå~ Ù„„BãáŠÅˆ†ÅÄñ0q3â
          3
          8ÄæڏÏñƒ[ÂLÞÓ2¥ÉʄX¥ýt‡wR<1Då(¹E›²)ãlÎ	¼¤m*ؚñ£¯Ìc ÿ¯f,NÏ¤6Οñž03Øщ3B˜JÃcçEÞ»ÿkIå+xO/ªç${řÛHÇv`‚œ<:fߢèÞ¶l~HI¡gmÄû »Pb`i¥ä)<6éìHžÄA,Œ§¬©8BdÓ#[y:,8çV6RJ;nÅïøùf:ü8?|øméŽy%/?úÚÑJ³^íÃöíØI~ҁÛÇæÝÏØ5­•†mª(k{ <õ|´g™°‰Mi?ÝX\ø½;›õ(˜*މlÒË´Í4lÓÌÚP²I§#–H¾ðán$ë<ÅwɓŽ,G)%£d©˜`R2´Å÷‡S¨	))ilvüßÌ(Qò¸™‡@Ã@È-ç^œtót¤¶ceóÍ؍ãäóM ¡p+>ãÇöÜLY2‘ÁKÖ©on…ÃÜ&%óÔ¬_|#ù¥dHP/͝ž¡“‡diJ­Òâ€EGÆHƒ1JÙ8á´øAFEúÛkÅ	6³Eµ3ÒÄÁR[¤9ØFv2.
          £&êAóãD÷`»M¸ƒ…Œ#»RáóÙ¸Iro¹å–{GÝïÿûÕøœÜ'
          ÌCpé™"
          ŵjÛÓÐ_¢@*
          ³ϱézíÆVœ‡>)™²¦Ãúø(]LøNàø(Ð2Ûq`»6Ðø읮 
          e‚˜I§òWç[›pÜ]h²hÇ5 yÌÀ¢d_ÁX+QLJª±¸h¯”R¾³Œp/«·ƒÉÑQ/%çÄ¥áA™²£fH”£jkkç̜9ó›#ÚXŠ‹#Þ»îºë0,Ü1|ÆȄM1Q9°pOˆû}ôÑ·{ì±å܊Íî+xöÙgçÝwß}w‰{÷íÛ÷ú”)SD=¦ÒÒÒ¯766ÓlŠŠŠb555žx`ßüùó÷³Åäò…)‹…«Ü»wïô#GŽL†1€5á÷ä¶	 S‡“+_„¬»üÚ֙§œÞìp4~–Â`7ký"?`hÉ~é/ïx»ÇäöGԓŠÓÞ½÷Ú²?2“	ݹhÁ/¯]¡1+÷¶Ï:ÞæÎð£gisVƒ&4©ØÖ°tjÞÎ4£&ûJÁŽé SMùÓÆ3÷ºõ”’´÷\Sö<.îã2wÙkꓫNüQï¿Í/]7½,£³c ˜÷â–æy Už¥ðiÕÊDÝà™\œvZh¬6£¦	.@æÿùÇïnï\­V)üv³îh0Óýò¶	ßG`Ê1sDUhgeÆŒÑ4‚¦¦&
          ”ôõë×ϙ={ö¤å˗¿ÔAÔLÁ(“|™Ífb»=R2ÏQCmY,–Lv¯?7hµÚ³š››UPÒÞÿýù?þxéƒ>ø&[</NªÁ+Ü(•ï½÷Þüºº:y^ýõ+n¾ùæ8N<åB*˜¦%½JŚýW®>àÀêG¶U‡>ӈŸK½Þ°ñýÎYM=¾üûU¼+ÆfÒ«U*…<§bqÌlìÄ	†"Iß;ÜyõêýÎb(6ÔNšI#iUJ	4>Éå‹HݖºžêÚú¾ŠoÍ)Ù4mLº8!ãO§r(•ƒmê4*¢Ž}L¶¥µM×j”Ck«VÉïUÐV–ŸO½Äø:}V(—­?ÜUsýÔÜ=sª³ö `»¹©úõ¿tx¬#M_wÊé¹6‘Ìl:÷–³-™LÂ⚨+Vơ̂7ÏŸù_|ñE3,–yÕªUi'NœPnß¾Ý û*¼ªdV¤$D	åË`0™l¡eäZV& Þ¡Ô/½^oÃIѪÕjyÂðƒøñ‹_%RïÚµKó³ŸýÌæóù?ýéOK'L˜0sá…}–¤LV$ýN§³jÛ¶mvªÿå—_kÆȊd;j¤xy(T>·¾aÙ¾3ý¹2èõjify†ëªª¬Æt³¦&\ŠÆuÇZÜYïí*rº‚gD	½ASbE£R˜ŒiƉÀ/@_{ céÆc]¶€UP
          NßÂɎ£VʋjfmîñînèË*ª~ÆÿÚа Ûo¹n²c/n(=$ƒÚT¶icr-Wš,j…bh¾á:%€ÓÏɟÉ6…~°¸¢C¥Tê;¼ºÓ^˱VwF}§W	@×¾¸µyv 3-œä؁sדaÖ6[
          jg^†aƒR¡p1?εH
          ³ÑC‹Ca$€ Õj•Ž¼óÎ;ÅÃÊ'Ÿ|2ýž{î™úÜsÏYΜ9£½âŠ+××ׯ•’1åCƒÐh4$8sõ{(Ñ€4¥‰ïeR“‘L&“gΜ9	(q(®Y³f•éµ×^›«eÊHß
          š³cǎ±@í†vão¼‘~ìرâqãÆ5’mIy.|ñÛûÚç¸*s͑;æ•î‡	¤³'üzJ–çŽËRB‰¿¼½ùr[6%_	;ö‹o2Á‚K×t~uã±n³W¶M¼÷Úòý¹iúv¦´Ä€ò3'§”¦åõš¶z_‡µß–ÞÚÝ6£,Ǭ̵ˆþ«5j…M5¼MÒxÕ)Q.å µ)…LðªU"@ÔÄaŒ¢Uù”øÒËr-â4Ȼ۳û ý7jÛ&uêÐUU™²Uá¡ecÿ&%N %p(K^Éì7²ÍHÁòÓb±eψKóþð‡Ý?þñeí±¡¡Aÿý÷ODžÍd*¯Ø*fCJmK
          ß«Ù½Cö7êBªí
          dÃ`UU•ìƒpq2
          lEûÙn·Û±zõêL v°áPX¹¾?ýéOcP¤éfb¿EHrñºƒr¸K^º!úÀÒ±Û\õ8f‘'Ï•sÿ?~Ûì¢\6ö?Q¦‹HãD=tH%åñMÇ»í;ã’Á‹{hYÕN—¯cíÂrS•µuÙ´ü~3&¶,ßÕ6™´O 6&ˆ"Ù¦*Å8,oj¥”d…ŠÁ÷À*/‘€G‹M%ú$AþÚwûUEí0ò}«ö¶OB.`BJEæ¨>"$S±Tá5א/zP¨;…üW÷­¿üå/Ν;W¾÷¯ýk#͆°üfA?ËyMÅf“M’T*Uœ-$Û$gëÖ­•ÀÞå6¾ÿý,Y’@6™…‹MZ•l´¯2°+éþEåPc¼Ç-ŠÈrªÅÏØêlù„±(ÁøÙ¹ƒ
          fÊêvK»|%ÝîA³È4§,zu‚ëÖ½‡:æ ejiځË+ì2ˆ»}Ö#-bÎ-@t/cv1v;>h„ãn@°‹öEiSM¡í(ˆrÇüݺƒãÙZû™Fía揑Ý)Œ‚…pòœˆè#0Áfzî¸ã9‰Áëõ*Ö®]›ÉŒ£Óe§àØŒ®··WÈb:Ô*Ìð§Aö(›=Ö¬YSØÓÓ#×ñÝï~7 “ãà;::ÔO=õTµ”LžÍÇ÷iG[ݲÂQî0ûa§’kë$.ð	ÿi¶³Ob(MÛÀâg¥§ò(“4Ð0'÷zMH †®žs¹C¶sëo`m‹ïueûøk[ºiŠì8Ù+Ï7L•öc$EãÆMp
          æf ;ŠE¼ïœPdkͱ
          F	iqç3å%Ɣ­ §úp€1Ó?Y…»¢‰ô_wÝu-vû ½{÷n3s«|œ¨¾’ä2AÆm‘H$ýàÁƒÙ—_~y*€{s=i‰*Ò1aݺurn¿ýöà˜1c¢ÕÕÕþk¯½–„ýRfLTÀêuFŸ7,›fWÚÛÐì҉àéDìJ3iÇR2I(>²'„l£7µ9Fv¥å[ÉhJ)g‚Åx €h‹¢,p¾åïAnÉK\à>_Dv/¶>î|§^1æòëeí÷eZtíÔ~Ç ½N›â2×YBbrÑù\äù'ׁ/;;{ ++KfUýýýÜÿÇY/ç•¡$€½ðºË.»,¨UÆäɓÓO:%ñðÃ7ƒrq5Hî$Y–
          W÷ÉÏç;߀H€²‘¸õÖ[#ho3mÙ²¥–ƒÔk(ù¾+Å%&<ʝÔXRÝ"#á‹gVi<¡¨mHkÖ(yhw€É-Cí0W,@ƒàï
          "ÏwC§W^X…¤‰€)Îãý¹(–¡ÓŒ ý~™ÜGa>a~TõhXRJñb#5?ò,Ðá½t ‡„,MÚ¿¿B¼Škƌ±W_}µù‘G©Åßƒ‹"§èƒÂQ¶|ùrÙÌRXX¿úê«iÁ7ÜpC°¼|0*ù7¿ùMôÍ üª¤OáÒ¨”ѳ䀏X9×=¼(?"ÀFâf#pãB"/È_%ËE]]]Öîîn%Ûq<u^6²0F•R„¶¨¡ÿCŽëE‹
          -ÈÝwßêÔ}Ë-·t2hwÐh²6oÞ\~àÀùþŸüä'¡@  öûý*(j`«‰o|ãq4Y¤Œ–‰Â·q|¡u€Ú©ksg3׉œnà×p§¸p/±ã§†vð«æ6aþÏ@8F¶G’1y`oÅþÆšnzç@P‰š®¬Y'¤×-FšçdtˆbD€%F*µOÚº„û´OHM½1j2³ò;…ÿ֏‘ûø„P
          ÚZÞò@-ú™€'¡¦§f®šLŠNu˜yèÄ¢|'NŒ?ôÐCr}Ï=÷œòÍ7ß´0­’BM¸²Ng!Ç*Lâº÷Þ{
          F£1Íd2e@I‡÷ÖÇ|h¼ —`t 9Æ@›“ÝÛ ÛÁÈ#Q€c¶BŸLPÈ$bC]JþŽ#ŒQ(òéÒ͚«AM@ÎBÅ$eAÙÄ#ڀb”’)~yxOF[_  ½0od!9Š¦*ÂÚ¤911/m½rp3›ïÄÙçðÓíؾ,«v{By½žA
          ؑ¦w1ö¸}(À :)yH‰à/"[¥Ý*Y¿ûÝïd£$,`~¢,>fó ˾ªKÑSJÑõõõ²Õ?33SÒét$τṡÎüêW¿òWUUÉÜsÏ=¦={öؙ{'Ÿd)­Æìܹó¼Éñ+¯¼bãTcB±MhOÈcføI	ýO®,øy%ZÿpŽŒ*fhU
          ßdÉmDÆØNä¦Èå¤[¸syDzvʱ^ÑÎ8œï’P$ž}ËïG%abqšœLÂK$”m)Ö1ÿ·Gã	S]ƒçl$†¥‘ƒÏSûâ}ö‰6OAKï`îʸk*8×=€)Ñ4@Zœ…K÷.ÃF|ðÁ)›6mR¡0M‰	²fD‚?€!]b'?C!»Ñ—	 M4žžžN‘®ÁX,Ff9Ž„}Ù¨,Yúá8Æëõæ ÈÅ–y<ž|Ðs€]Ëρß
          Ûò0”-PÖAÙe/”ÓkÖ¬‘7@{{»ê™gžÉ¢ø­…§…ËFøŸ[_?e,ŽY’§áëtüLŒc,°rÜé&áˆ$.`3HÉÜPa{SÛÍÚ¾Ê\Kù5Wîm/ó£bÂÀ;…µ3_i¾kz§í=Ó¯!ÇÌòaÎè2jU øÇE²#1˜†ó.’y¸Å=t¤{–U‡‹`HÚ2Gq ('`ŸÄkñþÆþI[ëzdÒjÔ¯›ì؃ëÝ/’&1cԂ‚é™ó¸'¼À5ý駟–O·)--
          ÂBmC{Ž|"h|²LóÚk¯™=š‹;¢w©XGkkkæ[o½%×QQQAñUr`]4•û‰DÄví6mZ×c=&,mÛ¶M	Bþ4ζoß^V[[+eá…曘Ýî 
          …íªyæ̙ÍÕÕÕòøžþùLRɁäwÏ—Õ>hÈô«Ÿ~ûÄl[£$qÑjpU¯îhýö¬:q…)™ÜÓàÜ+@öO*²í»lLº_t*©þcEÝ§+XΨåD\T¹
          pÕæºî+ßÙÛ!²¯äº¿~yá.œk1ç`œ!ιÐhrå³ù‡ýÏí÷Eµ§{m(?EáA½ Á…IýE
          –.%‚G¬wÉÎS½Sÿ±½5‡L,K§äîaæ‹?54h,Œñôp8¬w»Ýv­V«‡,Z¹reæÛo¿.œÝ®,îj4ÄuÓæxꩧ¶Nš4ézaìÖY·}ñâÅ-z½> |/½ôRÉÏþs;ß
          !|ÿö·¿ÝÉÃy`ƒ‚°p:Dù裏v¬X±ÂZ¥ùü£åšk®©\²d‰˜`5—LÀFÉ(ڄÆÒ”Ð]@)}W]uUáñãÇÍ@A
          ‚
          ϝ;WPÈèÍ3v´÷æmqgžtz5?}õèìéeé³*ì
          v‹¶;‰«Ãј¾¾Ó—¹ápWiK¯_T)„2j"+E»ؖùL`K‰H4.2D_}z­Ê	»ÿ}—/¼`ç©>}—;¤{âÍã3eg÷$ÇiƒVår‘'±6wû‹êœž¬.¥ ¬âºazþî©cÒk¥äI=K¦86ÕÖ÷ÞäòE”Þx¦lAMvÚÕrT„ñ¸þ”Ó[°þpG±·¦çF
          \	E#„%$%°Ù4•R©õ…¢â´î,˜‘†¨¢öoœž¿6âvœ_'*[áÑd0Ü9pÇL>räȼ	&,>—¸wݺu«-hVŕ D/xøᇧÑý"bBêë듋¸@ðN•Ûà;‚|\¶Üß%Âsn¿ýöú¿ÿýïi3>|Ø1kÖ¬…L%Ü#mܸq°EÃ]wÝU}èÐ!)'''ÐÑÑñ<³„“œ AV/¨D9l–é@éæ¹\.iÁ‚Íëׯ_«hßþ÷-Ms¶Ôõ”
          ™€Ú[–nÉŽJþP2[®Âav>xýØu¢ß+ö´/…E1+(õúæUÅ»ª*³åœÌÕû;æ®9à, ÅCÖ%·#ˆ!¯Gä•^79w/€óô tà†T¸üD»gæ3ëN…BŒ´ØgY´`õL,²µüυåk)VÌÙ¬|i[Ó5°¡>t½u Ý<«`לj\äÉhFc¬_%…PÍb©{ê†Åë­ÆcÀþÜ,à°یHVaDž™ ®ï‰'ž˜	À°KVWMMû׿þõÐ>IÉs±dÁ(§¼Ü^ùøÎï}ï{i@ñ.ojj’î»ï¾Jø,,À%®;ï¼s3¾AJž/æÅqúI˜1cFpìر3víÚeÜ°aCQcccOIII~Ÿ@pÍŸ]öFmëØÁá˜N8œ=6sÏÒËdv!¾4xÑPƒøhæ¨ÇƒTU>9hñ‡kú˜ô’{Ûglre
          p¤¶­Ì³´‹ô¿B»±Ç֌HÂ
          ›g‰ÿâ֚®?¿æÚºvO†-–0+@_kúìÂùäÌËT62š&?Ãà›Pd;3|ö›Q#Ž×:ƒ®Âv)™$=z+&;X¤ävŽ2`I^ߊî”n\@òpª+뱠Ʀd	nœ¤VÏ¥A­+ß{Y0¡µ2úµZƒ4ü<
          /öÃÉ
          ÙÊT,VlHíg‚œ´Qæ Pf3s‡(RúߏD{ý¢n>“ Ë\ln–ÐÍÂÆM,J—Ä–a€*/«'7e¾­8ß*&þxpžé$Ä0ÞC‘¼9øÜHI.6rŸõ±¤’ćO,†œþbe©I|b{™áeñßܗE¾6+‚ÌO{á1ÞÞ#%Ï+¥Cã”,$ÚÆÆ¡Tü¡_ç`‹åg	*>ì“JJf­aýÊ`}çbÆ^Ûtdõ/‘|†2«º¤äoXR€Ì“ri®zRBbÌÐÉçۖ2ßAiøODStø99¸-)I”üKÇjÑzS¢Ë9“¡¬":˜÷\ik„hJÙ¢CábŒLª¥‘€&/žâës3!‘bÂôl1Ã)uRv{‚M"ùõø¹ó©¿gDy´QCa!6d¦ÃóxVQx„ñ“‘“Œ›©YH4VN‘ulŽøÔó0úE?O_Í,îfÜÈ)XXžòb£qZÙ8%¶‘ü#¬wDžzN€3ñVþ³t<!3>Š?L•R—:ÅqeõÅ”Ìažz´÷,¨SØIL:ûÜøÄfµ4<§0!}B4O¾Õ¦´5Ò\H,ô\âüKgÿ¤õM)
          OòU§xRbŒBk\6ß±Úçkğ“Rúa`¿à£žõ€ýK×¥ë“vv_º.]—véúl]ÿ_€‚D"9‹gjIEND®B`‚
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        7. GET https://dev.duracloud.org/duradmin/images/wait.gif
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (363 bytes)
          GET https://dev.duracloud.org/duradmin/images/wait.gif HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (436 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: image/gif
          Content-Length: 1583
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"1583-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (1583 bytes)
          GIF89açAAAÿÿÿEEEÔÔԛ››ùùùááá^^^€€€ííí¦¦¦²²²TTTŒŒŒjjjÈÈȾ¾¾ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ÿNETSCAPE2.0!ù	
          ,j`@
           À€8 € ðâAŽ 2h`€@B8h Á‚”¬€c̔ 8ðÒàF
          €ð dB }PÀ€ƒŠ4êPÁх'ÒÜ*0 !ù	
          ,np`À<  A.„``@(€€ p`€@B0`°‘Á‚0(©€Ç˜(U
          8°òe̎€€ AI‰H0À€Èš$P°±¦ ÖTèàAU!ù	
          ,p €x€À	0ð(@4`àà0°Àã”&ª4@`!€AÂTÈ`Á(xà€Aš)@(`@Á~$ÑÀR+>@`0åBY!ù	
          ,k €A
          <@`€(p°‚ØHQ
          p0 @‚Ž
          ˆÐÂ28`P €›2x€@&(ð &ƒÝx1£˜6#6|H æ@„ÜÊu`@!ù	
          ,i €A 0ÀÀh0` D$x€40  "‚‡28™`€ƒhpB‚h‰$M†P` HB҄`À"ÆJ.lˆR"Aƒ¢Zµ!ù	
          ,t(€	$``€àÀ @$ð A40@@À	<p Á‚00 ÀĈÉ`À‚˜<0Ä  @‚@0°€@EJ@² „&K@@;
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        8. GET https://dev.duracloud.org/duradmin/jquery/dc/api/durastore-api.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (378 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/api/durastore-api.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 17975
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"17975-1638286296000"
          Last-Modified: Tue, 30 Nov 2021 15:31:36 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (17975 bytes)
          /**
           * 
           * @author Daniel Bernstein
           */
          
          /**
           * Durastore API 
           */
          
          var dc; 
          (function(){
          	if(dc == undefined){
          		dc ={};
          	}
          	
          	dc.store = {};
          	
          	/**
          	 * @param String spaceId  space id 
          	 * @param Object callback The callback must implement success and failure methods.
          	 * @option Function success(spaces) spaces is an array of spaces objects
          	 * @option Function failure(info) 
          	 * @param Object options
          	 * @option String marker - the last content item id of the previous page
          	 * @option String prefix - a filters the results to show only those matching the prefix
          	 */
          
          	 dc.store.GetSpace = function(storeProviderId,spaceId,callback,options){
          		if(options == undefined){
          			options = {};
          		}
          		
          		var marker = '';
          		if(options.marker){
          			marker = options.marker;
          		}
          
          		var prefix = '';
          		if(options.prefix){
          			prefix = options.prefix;
          		}
          
          		var recount='';
                  if(options.recount){
                      recount = '&recount=true';
                      
                  }
          		
          		return dc.ajax({
          			url: "/duradmin/spaces/space", 
          			data: "storeId="+storeProviderId+"&spaceId="+encodeURIComponent(spaceId)+"&prefix="+encodeURIComponent(prefix)+"&marker="+encodeURIComponent(marker)+recount,
          			cache: false,
          			async: options.async != undefined ? options.async : true,
          			context: document.body,
          			success: function(data){
          				callback.success(data.space);
          			},
          		}, callback);		
          	};
          	
              dc.store.GetSpace2 = function(params){
                  var marker = '', prefix = '', async = true;
                  if(params.marker != undefined){
                      marker = params.marker;
                  }
                  if(params.prefix != undefined){
                      prefix = params.prefix;
                  }
                  if(params.async != undefined){
                      async = params.async;
                  }
          
                  return dc.ajax2({
                      url: "/duradmin/spaces/space", 
                      data: "storeId="+params.storeId+
                            "&spaceId="+encodeURIComponent(params.spaceId)+
                            "&prefix="+encodeURIComponent(prefix)+
                            "&marker="+encodeURIComponent(marker),
                      cache: false,
                      async: async,
                  });       
              };
          	
              dc.store.UpdateSpaceHlsStreaming = function(storeId, spaceId, /*bool*/enable){
                  var jqxhr = dc.ajax2({
                      url: "/duradmin/spaces/mediastreamer/hls?storeId="+storeId+"&spaceId="
                      + encodeURIComponent(spaceId)
                      + "&enable=" + enable,
                      type: "post",
                      cache: false,
                  }).fail(function(){
                      dc.displayErrorDialog(jqxhr);
                  });
                  return jqxhr;
              };
              
               
          	/**
          	 * @param Object space
          	 * @param Object callback The callback must implement success and failure methods. options begin method is supported.
          	 */
          	dc.store.DeleteSpace = function(space, callback){
          		return dc.ajax({
          			url: "/duradmin/spaces/space/delete", 
          			data: "storeId="+space.storeId+"&spaceId="+encodeURIComponent(space.spaceId),
          			type: "POST",
          			success: callback.success,
          		    failure: callback.failure,
          		}, callback);
          	};
          
          	/**
          	 * @param String space  space
          	 * @param bool publicFlag  indicates whether the space should be created with public access enabled. 
          	 * @param Object callback The callback must implement success and failure methods. options begin method is supported.
          	 */
          	dc.store.AddSpace = function(space, publicFlag, callback){
          		dc.ajax(
          			{
          				url: "/duradmin/spaces/space", 
          				data: "storeId="+space.storeId+"&spaceId="+encodeURIComponent(space.spaceId)+"&publicFlag="+publicFlag,
          				type: "POST",
          				success: function(data){
          					callback.success(data.space)
          				},
          			    failure:callback.failure,
          			},callback);
          	};
          
          	/**
          	 * Returns a list of spaces
          	 * @param String storeProviderId The id of the store provider
          	 * @param boolean writeableOnly Indicates that only spaces writeable 
          	 *                              for the current caller should be returned
          	 * @param Object callback
          	 * @option Function success(spaces) a handler for an array of spaces
          	 * @option Function failure(info) a handler that returns failure info 
          	 */
          	dc.store.GetSpaces = function(storeProviderId, writeableOnly, callback, async){
          		dc.ajax({ 
          				url: "/duradmin/spaces/json", 
          				data: "storeId="+storeProviderId+"&writeableOnly="+writeableOnly,
          				cache: false,
          				async: (async != undefined ? async : true),
          				success: function(data){
          					callback.success(data.spaces);
          				},
          				failure:callback.failure,
          		},callback);
          		
          	};
          	
          	/**
          	 * params: storeProviderId, writeableOnly, async
          	 */
              dc.store.GetSpaces2 = function(params){
                  var writeableOnly = false,
                      async = true;
                  
                  if(params.writeableOnly){
                      writeableOnly = params.writeableOnly;
                  }
          
                  if(params.async){
                      async = params.async;
                  }
          
                  return dc.ajax2({ 
                          url: "/duradmin/spaces/json", 
                          data: "storeId="+params.storeId+"&writeableOnly="+writeableOnly,
                          cache: false,
                          async: (async != undefined ? async : true),
                  });
                  
              };
          	
          	/**
          	 * returns contentItem details
          	 */
          	dc.store.GetContentItem = function(storeProviderId, spaceId, contentItemId, callback){
          		return dc.ajax({
          				url: "/duradmin/spaces/content",
          				data: "storeId="+storeProviderId+"&spaceId="+encodeURIComponent(spaceId)+"&contentId="+encodeURIComponent(contentItemId),
                          cache: false,
          				success: function(data){
          					callback.success(data.contentItem);
          			    },
          			    failure: callback.failure,
          		},callback);
          
          	};
          	
          	/**
          	 * @param Object contentItem
          	 * @param Object callback The callback must implement success and failure methods. optional begin method is supported.
          	 */
          	dc.store.DeleteContentItem = function(contentItem, callback){
          		dc.ajax({
          			url: "/duradmin/spaces/content/delete", 
          			data: "storeId="+contentItem.storeId+"&spaceId="+encodeURIComponent(contentItem.spaceId)+"&contentId="+encodeURIComponent(contentItem.contentId),
          			type: "POST",
          			success: callback.success,
          		    failure: callback.failure,
          		},callback);
          	};
          
          	dc.store._appendNVPair = function(name, value){
          	    return "&"+name+"="+encodeURIComponent(value);
          	};
          
          	/**
               * @param Object contentItem
               * @param Object callback The callback must implement success and failure methods. optional begin method is supported.
               */
              dc.store.copyContentItem = function(storeId, spaceId, contentId, destStoreId, destSpaceId, destContentId, deleteOriginal, callback){
                  var anvp = dc.store._appendNVPair;
                  return dc.ajax({
                                  url: "/duradmin/spaces/content/copy", 
                                  data: "".concat(
                                        anvp("deleteOriginal", deleteOriginal),
                                        anvp("storeId", storeId),
                                        anvp("spaceId", spaceId),
                                        anvp("contentId", contentId),
                                        anvp("destStoreId", destStoreId),
                                        anvp("destSpaceId", destSpaceId),
                                        anvp("destContentId", destContentId)
                                      ),
                                  type: "POST",
                                  success: function(result){
                                      callback.success(result.contentItem);
                                  }
                              },callback);
              };
          
          	
          	/**
          	 * @param Object serialized form data
          	 * @param Object callback The callback must implement success and failure methods. optional begin method is supported.
          	 */
          	dc.store.UpdateContentItemMimetype = function(data, callback){
          		dc.ajax({
          			url: "/duradmin/spaces/content/change-mimetype", 
          			data: data,
          			type: "POST",
          			success: function(data,xhr){
          				if(data.contentItem != undefined){
          					callback.success(data.contentItem);
          				}else{
          					this.failure(data,xhr);
          				}
          			},
          		    failure: callback.failure,
          		},callback);
          	};
          
          	/**
          	 * Adds a content item.  
          	 * @param Object/String a reference to a form dom node or the form's id
          	 * @param Object future an object implementing a success and failure method.
          	 */
          	dc.store.AddContentItem = function(form, future){
          
                  $(form).ajaxSubmit({
          			iframe: true,
          			dataType: 'json',
          			success: function(){
          				dc.checkSession();
          				future.success(data);
          		    },
          		    error: function(xhr, status, errorThrown){
          		    	future.failure(status,xhr);
          		    },
          		});
          	};
          	
          	/**
          	 * checks if the content item already exists
          	 * @param spaceId
          	 * @param contentId
          	 * @param storeId 
          	 * 
          	 */
          	dc.store.CheckIfContentItemExists = function(contentItem, callback){
          		dc.store.GetContentItem(contentItem.storeId,contentItem.spaceId,contentItem.contentId,{
          			begin: function(){
          			},
          			
          			failure: function(text){
          				callback.success(false);
          			},
          
          			success: function(contentItem){
          				callback.success(contentItem != undefined);
          			},
          		});
          	};
          	
          	/**
          	 * 
          	 */
          	dc.store.formatJ2kViewerURL = function(/*string*/j2kViewerBaseURL, /*object*/contentItem, /*boolean*/ openSpace){
          		var contentUrl = contentItem.durastoreURL;
                  if(!openSpace){
                      contentUrl = contentUrl.replace("http://", "https://");}
                  return j2kViewerBaseURL + "/viewer.html?rft_id=" + encodeURIComponent(contentUrl);
          	};
          
              /**
               * Retrieves an HLS streaming URL for a given content item in a given space.
               * The URL will be either open or secure, depending on the streaming type.
               */
              dc.store.GetHlsUrl = function(contentItem, hlsStreamingType, callback){
                  return dc.ajax({
                      url: "/duradmin/spaces/content/hls-url",
                      data: "storeId="+contentItem.storeId+
                      "&spaceId="+encodeURIComponent(contentItem.spaceId)+
                      "&contentId="+encodeURIComponent(contentItem.contentId)+
                      "&hlsStreamingType="+hlsStreamingType,
                      cache: false,
                      success: function(data){
                          callback.success(data);
                      },
                      failure: function(data){
                          callback.failure(data);
                      }
                  },callback);
              };
          	
          	/**
          	 * 
          	 */
          	dc.store.formatThumbnail = function(/*object*/contentItem, /*int*/ size, /*optional - string*/j2kViewerBaseURL, /*boolean*/ openSpace ){
                  var contentUrl = contentItem.durastoreURL;
                  if(!openSpace)
                      contentUrl = contentUrl.replace("http://", "https://");
                  return j2kViewerBaseURL+
              			"/resolver?url_ver=Z39.88-2004&rft_id="+encodeURIComponent(contentUrl)+"&" +
                          "svc_id=info:lanl-repo/svc/getRegion&svc_val_fmt=info:ofi/fmt:kev:mtx:jpeg2000&" +
                          "svc.format=image/png&svc.level="+size+"&svc.rotate=0&svc.region=0,0,500,500";
              };
          
          
          	var GENERIC_THUMBNAIL_PREFIXES = ["image", "video", "text", "pdf"];
          	
          	/**
          	 * 
          	 */
              dc.store.formatGenericThumbnail = function(/*object*/contentItem){
                  var mimetype = contentItem.properties.mimetype;
              	var gtf,i;
              	for(i in GENERIC_THUMBNAIL_PREFIXES){
              		gtf = GENERIC_THUMBNAIL_PREFIXES[i];
              		if(mimetype.indexOf(gtf) == 0){
              			return "/duradmin/images/generic-thumb-" + gtf + ".png";
              		}
              	}
              	return "/duradmin/images/generic-thumb-other.png";
              };
              
              /**
               * 
               */
          	dc.store.formatDownloadURL = function(/*object*/contentItem, /*boolean*/ asAttachment){
          		if(asAttachment == undefined) asAttachment = true;
          		return "/duradmin/download/contentItem?spaceId=" +  encodeURIComponent(contentItem.spaceId) +
          			   "&contentId=" + encodeURIComponent(contentItem.contentId) + "&storeID=" + contentItem.storeId +
          			   "&attachment=" + asAttachment;
          	};	
          
          	/**
          	 * @param storeId
          	 * @param spaceId
          	 */
              dc.store.GetUnassignedSpaceAcls = function(storeId,spaceId, callback){
                  dc.ajax({
                      url: "/duradmin/spaces/acls/unassignedAcls?storeId="+storeId+"&spaceId="+spaceId, 
                      async: false,
                      cache: false,
                      success: function(data){
                          callback.success(data.acls);
                      },
                  }, callback);
              };
              
              /**
               * @param storeId
               * @param spaceId
               */
              dc.store.GetSpaceAcls = function(storeId,spaceId, callback){
                  dc.ajax({
                      url: "/duradmin/spaces/acls?storeId="+storeId+"&spaceId="+spaceId, 
                      async: false,
                      cache: false,
                      success: function(data){
                          callback.success(data.acls);
                      },
                  }, callback);
              };
              
              /**
               * @formData is serialized form data containing the following required fields:
               *             storeId 
               *             spaceId
               *           and one or more of the following non required fields:
               *             read (users/groups to give read access to)
               *             write (users/groups to give write access to)
               * @param add - optional parameter. If value is set to true the acls in the form
               *               will be added to the existing space acls rather than replacing them.              
               *             
               */
              dc.store.UpdateSpaceAcls = function(/*serialized form data*/formData, /*boolean*/ add, callback){
                  dc.ajax({
                      url: "/duradmin/spaces/acls?action="+(add ? "add":""), 
                      async: true,
                      data: formData,
                      type: "post",
                      success: function(data){
                          callback.success(data.acls);
                      },
                  });
              };
              
              
             /**
              * @param storeId
              * @param spaceId (optional)
              */
              dc.store.GetStorageStatsTimeline = function(storeId,spaceId, start, end){
          
                var url =  "/duradmin/storagestats/timeseries?storeId="+storeId;
                if(spaceId){
                  url = url + "&spaceId="+spaceId;
                }
          
                if(start){
                  url = url + "&start="+start.getTime();
                }
          
                if(end){
                  url = url + "&end="+end.getTime();
                }
          
                return dc.ajax2({
                      url: url, 
                      dataType: 'json',
                      async: false,
                      cache: false});
              };
            
              dc.store.GetStorageStatsSnapshot = function(storeId,date){
                var url =  "/duradmin/storagestats/snapshot-by-day?storeId="+storeId;
                url = url + "&date="+date.getTime();
                  return dc.ajax2({
                      url: url, 
                      dataType: 'json',
                      async: false,
                      cache: false});
              };
          
          
              
              dc.store.CreateSnapshot = function(/*serialized form data*/formData){
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshot", 
                      async: true,
                      dataType: 'json',
                      data: formData,
                      type: "post",
                  });
              };
          
              dc.store.RestoreSnapshot = function(storeId, snapshotId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/restores?storeId="+storeId+"&snapshotId="+snapshotId, 
                      async: true,
                      dataType: 'json',
                      type: "post",
                  });
              };
          
              dc.store.RequestRestoreSnapshot = function(storeId, snapshotId){
                return dc.ajax2({
                    url: "/duradmin/spaces/restores/request?storeId="+storeId+"&snapshotId="+snapshotId, 
                    async: true,
                    dataType: 'json',
                    type: "post",
                });
            };
          
              dc.store.GetSnapshots = function(storeId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshots/" + storeId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
          
              dc.store.GetSnapshotTotals = function(storeId, status) {
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshots/totals/" + storeId + "?status=" + status,
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
          
              dc.store.GetSnapshot = function(params){
                  
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshots/" + params.storeId + "/" + params.spaceId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
              
              dc.store.GetSnapshotRestoreSpaceId = function(params){
                return dc.ajax2({
                    url: "/duradmin/spaces/snapshots/" + params.storeId + "/" + params.snapshotId + "/restore-space-id", 
                    async: true,
                    dataType: 'json',
                    type: "get",
                });
            };
              
             
              dc.store.GetRestoreBySnapshot = function(storeId,snapshotId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/restores/"+storeId+"/by-snapshot/" + snapshotId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
              
              dc.store.GetRestore = function(storeId,restoreId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/restores/"+storeId+"/"+restoreId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
                  
              
              
              dc.store.GetSnapshotProperties = function(storeId, spaceId){
                  
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshot?storeId="+ storeId + "&spaceId="+spaceId, 
                      dataType: 'json',
                      async: true,
                      type: "get",
                  });
              };
          
              dc.store.GetSnapshotContent = function(storeId, snapshotId, page, prefix){
                  if(!page){
                      page = 0;
                  }
                  return dc.ajax2({
                      url : "/duradmin/spaces/snapshots/" + storeId + "/" + snapshotId
                              + "/content?page=" + page + "&prefix="
                              + prefix,
                      dataType : 'json',
                      async : true,
                      type : "get",
                  });
              };
              
              dc.store.GetSnapshotHistory = function(storeId, snapshotId, page){
                  if(!page){
                      page = 0;
                  }
                  
                  return dc.ajax2({
                      url : dc.store.formatSnapshotHistoryUrl(storeId, snapshotId, page, "false"),
                      dataType : 'json',
                      async : true,
                      type : "get",
                  });
              };
              
              dc.store.formatSnapshotHistoryUrl = function(storeId, snapshotId, page, attachment) {
                return "/duradmin/spaces/snapshots/" + storeId + "/" + snapshotId
                + "/history?page=" + page + "&attachment=" + attachment;
              };
          
          })();
          
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        9. GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.dc.common.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (381 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.dc.common.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 17903
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"17903-1574428024000"
          Last-Modified: Fri, 22 Nov 2019 13:07:04 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (17903 bytes)
          /*
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           *
           * @author "Daniel Bernstein (dbernstein@duraspace.org)"
           */
          
          var dc;
          
          $(function(){
          	(function(){
          		///////////////////////////////////////////////////////////////////////
          		////duracloud js utils
          		///////////////////////////////////////////////////////////////////////
          		if(dc == undefined){
          			dc = {};
          		}
          
          
          		dc.log = function(message){
          			if(window.console){
          				console.log(message);
          			}
          		};
          
          		dc.debug = function(message){
          			if(window.console){
          				if(window.opera){
          					console.log(message);
          				}else{
          				    if(console.debug){
          	                    console.debug(message);
          				    }else{
          				        console.log(message);
          				    }
          				}
          			}
          		};
          
          	    dc.logXhr = function(xhr, message){
                     dc.error("status="+xhr.status + "; statusText="+xhr.statusText);
          	    };
          
          		dc.error = function(message){
          			if(window.console){
          				if(window.opera){
          					console.log(message);
          				}else{
          					console.error(message);
          				}
          			}
          		};
          
              dc.checkSession = function(data){
                if(data != undefined && data != null){
                  if(data.responseText){
                    data = data.responseText;
                  }
                  if(data.toString().indexOf("loginForm") > -1){
                    alert("Your session has timed out.");
                    window.location.reload();
                  }
                }
              };
          
          		dc.displayErrorDialog = function(xhr, textStatus, errorThrown, showStackTrace){
          			var errorText = xhr.responseText;
          
          
          			if(!textStatus){
          			    textStatus = "An unexpected error occurred:";
          			}
          
          			if(showStackTrace == undefined || showStackTrace == null){
          			  showStackTrace = true;
          			}
          
          			try{
          				var response = $.parseJSON(errorText);
          				errorText = "cause: " + response['exception.message'];
          				errorText += "; stacktrace: " + response['exception.stacktrace'];
          			}catch(error){
          
          			}
          
                dc.error("error: " +
                         errorThrown +
                         "; response=" +
                         errorText);
          
          	     var options = {
          	                    autoOpen: true,
          	                    show: 'fade',
          	                    hide: 'fade',
          	                    width:500,
          	                    resizable: true,
          	                    closeOnEscape:true,
          	                    modal: true,
          	                    buttons: {
          	                      "Close": function(){
          	                        $(this).dialog("close");
          	                        errorDialog.empty();
          	                      },
          	                    },
          	                  };
          
          
          			var errorDialog = $.fn.create("div");
          
          			$(document).append(errorDialog);
          			errorDialog.append("<h2>"+textStatus+"</h2>");
          
                if(showStackTrace){
          
                  errorDialog.append("<div><button>Show Details</button>" +
                                     "<div class='error-detail' style='overflow:auto;height:200px;display:none'>" +
                                     "<pre>"+errorText+"</pre></div>");
          
                  errorDialog.find("button").click(function(){
                    errorDialog.find(".error-detail").show();
                  });
          
                  options = $.extend(options, {
                    height: 350
                  });
                }
          
          
          			errorDialog.dialog(options);
          		};
          
          
          		dc.ajax2 = function(settings){
          		    return $.ajax(settings)
                            .error(function(data){
                              dc.checkSession(data);
                            })
                            .done(function(data) {
                              dc.checkSession(data);
                            });
          
          		};
          
          		dc.ajax = function(innerCallback, outerCallback){
          			var callback = $.extend(
          					true,
          					{},
          					innerCallback,
          					{
          						success: function(data, status, xhr){
          							dc.checkSession(data);
          							if(innerCallback.success != undefined){
          								innerCallback.success(data, status, xhr);
          							}else{
          								if(outerCallback != undefined
          										&& outerCallback.success != undefined){
          									outerCallback.success(data, status, xhr);
          								}
          							}
          						},
          						error: function(xhr, textStatus, errorThrown){
          							dc.error(xhr.responseText);
          							if(innerCallback.failure != undefined){
          								innerCallback.failure(textStatus, xhr, errorThrown);
          							}else if(outerCallback != undefined
          										&& outerCallback.failure != undefined){
          									outerCallback.failure(textStatus, xhr, errorThrown);
          							}else{
          								//default error handler
          								dc.done();
          								dc.displayErrorDialog(xhr, textStatus, errorThrown);
          							}
          						},
          
          						begin: (innerCallback.begin != undefined ? innerCallback.begin :
          								(outerCallback != undefined && outerCallback.begin != undefined ? outerCallback.begin : undefined)),
          					}
          			);
          
          			if(callback.begin != undefined){
          				callback.begin();
          			}
          
          			return $.ajax(callback);
          		};
          		/**
          		 * Create a cookie with the given name and value and other optional parameters.
          		 *
          		 * @example dc.cookie('the_cookie', 'the_value');
          		 * @desc Set the value of a cookie.
          		 * @example dc.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
          		 * @desc Create a cookie with all available options.
          		 * @example dc.cookie('the_cookie', 'the_value');
          		 * @desc Create a session cookie.
          		 * @example dc.cookie('the_cookie', null);
          		 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
          		 *       used when the cookie was set.
          		 *
          		 * @param String name The name of the cookie.
          		 * @param String value The value of the cookie.
          		 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
          		 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
          		 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
          		 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
          		 *                             when the the browser exits.
          		 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
          		 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
          		 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
          		 *                        require a secure protocol (like HTTPS).
          		 * @author Klaus Hartl/klaus.hartl@stilbuero.de - modified by Daniel Bernstein
          		 */
          		dc.cookie = function(name, value, options) {
          		    if (typeof value != 'undefined') { // name and value given, set cookie
          		        options = options || {};
          		        if (value === null) {
          		            value = '';
          		            options.expires = -1;
          		        }
          		        var expires = '';
          		        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
          		            var date;
          		            if (typeof options.expires == 'number') {
          		                date = new Date();
          		                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
          		            } else {
          		                date = options.expires;
          		            }
          		            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
          		        }
          		        // CAUTION: Needed to parenthesize options.path and options.domain
          		        // in the following expressions, otherwise they evaluate to undefined
          		        // in the packed version for some reason...
          		        var path = options.path ? '; path=' + (options.path) : '';
          		        var domain = options.domain ? '; domain=' + (options.domain) : '';
          		        var secure = options.secure ? '; secure' : '';
          		        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
          		    } else { // only name given, get cookie
          		        var cookieValue = null;
          		        if (document.cookie && document.cookie != '') {
          		            var cookies = document.cookie.split(';');
          		            for (var i = 0; i < cookies.length; i++) {
          		                var cookie = jQuery.trim(cookies[i]);
          		                // Does this cookie string begin with the name we want?
          		                if (cookie.substring(0, name.length + 1) == (name + '=')) {
          		                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          		                    break;
          		                }
          		            }
          		        }
          		        return cookieValue;
          		    }
          		};
          
          		dc.createTable = function(data, /*optional: array*/ columnDefs){
          			var table, body, row, i,j;
          			table = $.fn.create("table");
          			if(columnDefs){
          				row = $.fn.create("tr");
          				$.each(columnDefs, function(x,item){
          					var h = $.fn.create("th").html(item.name);
          					if(item.cssClass){
          						//h.addClass(item.cssClass);
          					}
          					row.append(h);
          				});
          				table.append($.fn.create("thead").append(row));
          			}
          
          			body = $.fn.create("tbody");
          			table.append(body);
          
          			for(i = 0; i < data.length; i++){
          				row = $.fn.create("tr");
          				$(body).append(row);
          				for(j = 0; j < data[i].length; j++){
          					var value = data[i][j],
          							cell = $.fn.create("td");
          
          					$(row).append(cell);
          
          					if(columnDefs && columnDefs[j]){
          						if(columnDefs[j].formatter){
          							value = columnDefs[j].formatter(value);
          						}
          
          						if(columnDefs[j].cssClass){
          							cell.addClass(columnDefs[j].cssClass);
          						}
          					}
          					cell.append(value);
          				}
          			}
          			return table;
          		};
          
          		dc.getMimetypeImageClass = function(mimetype){
          		var mtc = "";
          		if(mimetype.indexOf("audio") > -1){
          			mtc = "audio";
          		}else if(mimetype.indexOf("image") > -1){
          			mtc ="image";
          		}else if(mimetype.indexOf("video") > -1){
          			mtc = "video";
          		}else if(mimetype.indexOf("xml") > -1){
          			mtc = "xml";
          		}else if(mimetype.indexOf("zip") > -1){
          			mtc = "compression";
          		}else{
          			mtc = "generic";
          		}
          		return "mime-type-" + mtc;
          
          		};
          
          		var spNameMap = {};
          		spNameMap["AMAZON_S3"] = "Amazon S3";
          		spNameMap["AMAZON_GLACIER"] = "Amazon Glacier";
                          spNameMap["SWIFT_S3"] = "Swift S3";
          		spNameMap["CHRONOPOLIS"] = "Chronopolis";
          		spNameMap["IRODS"] = "iRODS";
          		dc.STORAGE_PROVIDER_KEY_MAP = spNameMap;
          
          
          		dc.formatGB = function(value, decimalplaces, showUnits){
          			if(!decimalplaces){
          				decimalplaces = 0;
          			}
          
          			if(showUnits == undefined){
          				showUnits = true;
          			}
          
          			value = new Number(value/(1000*1000*1000));
          			value =  value.toFixed(parseInt(decimalplaces));
          
          			if(showUnits){
          				return value +"GB";
          			}else{
          				return value;
          			}
          		};
          
          		dc.busy = function(message, options){
          			var d =
          			   $("#busy-dialog");
          			var modal = false;
          			var buttons = undefined;
          
          			if(options != undefined){
          				if(options.modal != undefined){
          					modal = options.modal;
          				}
          
          				if(options.buttons != undefined){
          					buttons = options.buttons;
          				}
          			}
          
          			var dOptions = {
          					autoOpen: false,
          					show: 'fade',
          					hide: 'fade',
          					resizable: false,
          					height: 100,
          					closeOnEscape:false,
          					modal: modal != undefined ? modal : false,
          					width:300,
          					close: function() {
          
          					},
          
          					open: function(e){
          					},
          			};
          
          			if(buttons != undefined){
          				dOptions.buttons = buttons;
          			}
          
          			d.dialog(dOptions);
          
          		   $("#busy-dialog-title").html(message);
          
          		   if(!d.dialog("isOpen")){
          		       d.dialog("open");
          		   }
          		};
          
          		dc.done = function(message){
          			$("#busy-dialog").dialog("close");
          
          			if(message != undefined){
          				var d = $("#message-dialog");
          				d.dialog({
          					autoOpen: false,
          					show: 'fade',
          					hide: 'fade',
          					resizable: false,
          					height: 100,
          					closeOnEscape:true,
          					modal: false,
          					width:300,
          					buttons: {
          						"Close" : function(){
          							$(this).dialog('close');
          						 },
          					},
          					close: function() {},
          					open: function(e){},
          				});
          
          			   $("#message-dialog-title").html(message);
          			   d.dialog("open");
          			}
          		};
          
          
          		dc.confirm = function(message,evt){
          			if(!confirm(message)){
          				if(evt != undefined){
          					evt.stopPropagation();
          					evt.preventDefault();
          				}
          				return false;
          			};
          
          			return true;
          		};
          
          
                  dc.extractStoreId = function(path){
                      var index = path.indexOf("?storeId=");
                      if(index > 0){
                          return path.substring(index+9);
                      }else{
                          return null;
                      }
                  };
          
          	    dc.extractSpaceId = function(path){
          	        var index = path.indexOf("/");
          	        return path.substring(0, index);
          	    };
          
          	    dc.extractContentId = function(path){
          	        var index = path.indexOf("/");
          	        var qsIndex = path.indexOf("?");
          	        return path.substring(index+1, (qsIndex > 0 ? qsIndex : path.length));
          	    };
          
          	    dc.reportOverlayOnClick = function(link, storeId, spaceId){
                      var params = "&spaceId=" + spaceId;
                      if(storeId){
                          params+="&storeId="+storeId;
                      }
          
                      var prefix = "/duradmin/servicesreport";
          
                      var fileInfoUrl = prefix + "/info?" + params;
          
                      var jqxhr = $.getJSON(fileInfoUrl, function(data){
                          var size = new Number(data.fileInfo.size);
                          if(size > (1024*1000)){
                              link.attr("href", prefix + "/raw?attachment=true&" + params);
                          }else{
                              var url = prefix + "/htmltable?" + params;
                              link.attr("href", url)
                                  .attr("title","View Bit Integrity Report")
                                  .fancybox({type: 'iframe',
                                             width: 800,
                                             scrolling: 'auto',
                                             titleShow: false,
                                          });
                          }
                      });
          	    };
          
          		/**
          		 * checks the progress of a remote task and notifies caller of results.
          		 */
          		var DEFAULT_POLL_INTERVAL = 5000;
          
          		dc.checkProgress = function(url, key, callback){
          
          			if(callback.count == undefined){
          				callback.count = 0;
          			}
          
          			var updater = function(progressCallback, data){
          				if(data.error){
          					_error(data.message);
          					progressCallback.failure(message);
          					return;
          				}
          
          				progressCallback.update(data);
          				if(data.task != undefined){
          					var state = data.task.properties.state;
          
          					if(state == 'running' || state == 'initialized'){
          						setTimeout(function(){ dc.checkProgress(url,key, progressCallback); }, DEFAULT_POLL_INTERVAL);
          					}else if(state == 'success'){
          						if(progressCallback.success != undefined){
          							progressCallback.success(data);
          						}
          					}else if(state == 'cancelled'){
          						if(progressCallback.cancel != undefined){
          							progressCallback.cancel();
          						}
          					}else{
          						if(progressCallback.failure != undefined){
          							progressCallback.failure();
          						}
          					}
          				}
          			};
          
          			dc.ajax({ url: url,
          				cache: false,
          				type: "GET",
          				success: function(data){
          					//ajax response gets set here
          					updater(callback, data);
          			    },
          			    failure: function(textStatus){
          			    	alert("updater failed: " + textStatus);
          			    },
          			});
          		};
          
                  /**
                  * Login function
                  *
                  * @return jqXHR Jquery XmlHttpRequest object.
                  */
                  dc.login = function(/* jquery object */form) {
                      var message = $("#msg-error");
                      var feedback = $("#feedback");
                      return $.ajax({
                          type : "POST",
                          url : form.attr("action"),
                          data : form.serialize(),
                          cache : false,
                          beforeSend : function() {
                              message.makeHidden();
                              feedback.fadeIn();
                          },
                          complete : function() {
                              feedback.fadeOut();
                          },
                          success : function(data, textStatus, jqXHR) {
                              try {
                                  dc.debug("data=" + data);
                                  if (data.indexOf(form.attr("id")) > 0) {
                                      message.makeVisible();
                                      message.fadeIn();
                                  } else {
                                      location.reload(true);
                                  }
                              } catch (err) {
                                  dc.error(err);
                                  dc.displayErrorDialog(jqXHR, textStatus,
                                          "An unexpected error occurred: " + err);
                              }
                          },
                          error : function(jqXHR, text, errorThrown) {
                              dc.displayErrorDialog(jqXHR, text, errorThrown);
                          },
                      });
                  };
          
          
                  dc.formatBytes = function(bytes, showBytes){
                      var val = null;
                      bytes = new Number(bytes);
                      var bytesValue = bytes + " bytes";
          
                      if(bytes < 1000){
                          return bytesValue;
                      }else if(bytes < 1000*1000){
                         val = (bytes/1000).toFixed(1) + " KB";
                      }else if(bytes < 1000*1000*1000){
                          val = (bytes/(1000*1000)).toFixed(1) + " MB";
                      }else{
                          val = (bytes/(1000*1000*1000)).toFixed(1) + " GB";
                      }
          
                      if(showBytes){
                          val += " (" + bytesValue + ")";
                      }
                      return val;
                  };
          
          
                  dc.hexEncode = function(val) {
                    var hex, i;
          
                    var result = "";
                    for (i = 0; i < val.length; i++) {
                      hex = val.charCodeAt(i).toString(16);
                      result += ("000" + hex).slice(-4);
                    }
          
                    return result
                  };
          
                dc.hexDecode = function(val) {
                  var j;
                  var hexes = val.match(/.{1,4}/g) || [];
                  var back = "";
                  for (j = 0; j < hexes.length; j++) {
                    back += String.fromCharCode(parseInt(hexes[j], 16));
                  }
          
                  return back;
                };
          
          	})();
          });
          
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        10. GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.fn.ext.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (378 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.fn.ext.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 5462
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"5462-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (5462 bytes)
          /*
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           * A collection of useful jquery extensions
           * @author "Daniel Bernstein (dbernstein@duraspace.org)"
           */
          
          
          $(function(){
          	(function(){
          		////////////////////////////////////////////////////////////////////
          		//jquery extensions
          		///////////////////////////////////////////////////////////////////
          	    $.fn.disable = function(/*boolean*/ val){
          	        if(!val){
          	           return $(this).removeAttr("disabled");
          	        }else{
          	           return $(this).attr("disabled", "disabled");
          	        }
          	    };
          	    
          	    /**
          		 * Similar to hide/show jquery functions but toggles the visibility css 
          		 * attribute instead of the display attribute.
          		 */
          		$.fn.makeVisible = function(isvisible) {
          			return $(this).css("visibility", (isvisible == undefined || isvisible) ? "visible":"hidden");
          		};
          		
          		$.fn.makeHidden = function() {
          			return $(this).makeVisible(false);
          		};
          
          		
          		/**
          		 * This finds the nearest ancestor of the specified class.  It is just like jQuery.closest(selector) except
          		 * that it includes the dom node your are calling the function on.
          		 */
          		$.fn.nearestOfClass = function(className){
          			var nearest = (this.hasClass(className)) ? this : this.closest("." + className);
          			return $(nearest);
          		};
          
          		
          		$.fn.toggleOpenClosed = function(){
          			$(this).nearestOfClass("button")
          					.toggleClass("dialog-open")
          					.toggleClass("dialog-closed");
          		};
          
          		/**
          		 * Shorthand for document.createElement
          		 * Returns the new element as a jQuery object.
          		 */
          		$.fn.create = function(tag){
          			return $(document.createElement(tag));
          			
          		};
          		
          		/**
          		 * Scrolls the specified dom element to the top of the 
          		 * viewport (which is the object on which you're calling this function)
          		 * if possible. If it can't scroll it to the top of the viewport it at 
          		 * least scrolls the container so that the element is in view.
          		 * @param DOM node or jquery object
          		 */
          		$.fn.scrollTo = function(element){
          			var top = $(element).offset().top;
          			this.animate({scrollTop: top}, {duration:"slow", easing:"swing", queue:true});
          		};
          
          		/**
          		 * Returns true if the element is in the viewport
          		 */
           		$.fn.isVisibleInViewPort = function() {
           		        var rect = this.get(0).getBoundingClientRect();
          
           		        return rect.bottom > 0 &&
           		            rect.right > 0 &&
           		            rect.left < (window.innerWidth || document. documentElement.clientWidth) /*or $(window).width() */ &&
           		            rect.top < (window.innerHeight || document. documentElement.clientHeight) /*or $(window).height() */;
           		}
          
          		/**
          		 * this method loads the children of the new contents
          		 * into the target after emptying the contents
          		 * with a fade in / fade out effect
          		 */
          		$.fn.replaceContents = function(/*the pane whose contents will be swapped in*/ newContents,  
          										/*the layout for the target*/ layoutOptions){
          			var target = this;
          			//$(target).fadeOut("fast", function(){
          				$(target).empty().prepend($(newContents).children());
          				//$(target).fadeIn("fast");
          				if(layoutOptions != null && layoutOptions != undefined){
          					$(target).layout(layoutOptions);
          				}
          			//});
          			return $(target);
          		};	
          
          		/**
          		 * Closes the dialog when the user clicks off of it.
          		 */
          		$.fn.closeOnLostFocus = function() { // on the open event
          		    // find the dialog element
          		    var dialogEl = this;        
          		    $(document).click(function (e) { // when anywhere in the doc is clicked
          		        var clickedOutside = true; // start searching assuming we clicked outside
          		        $(e.target).parents().andSelf().each(function () { // search parents and self
          		            // if the original dialog selector is the click's target or a parent of the target
          		            // we have not clicked outside the box
          		            if ($(this).first().attr("id") == $(dialogEl).attr("id")) {
          		                clickedOutside = false; // found
          		                return false; // stop searching
          		            }
          		        });
          		        if (clickedOutside) {
          		            $(dialogEl).dialog("close"); // close the dialog
          		            // unbind this listener, we're done with it
          		            $(document).unbind('click',arguments.callee); 
          		        }
          		    });
          		};
          		
          		
          		/**
          		 * Binds the enter keyup event to the specified function.
          		 */
          		$.fn.bindEnterKey = function(func) {
          			$(this).bind('keydown', function(e){
          			    if(e.keyCode==13){
          		        	func(e);
          			    }
          			});		
          			
          			return this;
          		};
          		
          		$.fn.busy = function(){
          		    $(".dc-busy",this).show("fast");
          		    return this;
          		};
          
          		$.fn.idle = function(){
                      $(".dc-busy",this).hide();
                      return this;
                  };
          
          
              $.fn.busySibling = function(text){
                var busy = $("<div class='dc-busy-holder'></div>");
                if(text){
                  busy.html(text);
                }
                
                busy.insertAfter($(this));
                busy.show("fast");
                return this;
              };
          
              $.fn.idleSibling = function(){
                $(this).siblings(".dc-busy-holder").hide("fast").remove();
                return this;
              };
          
              //adds in missing addBack function for plugins that depend on it (namely jquery dropdown)
              $.fn.addBack = function (selector) {
                return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
              };
                  
          	})();
          });
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        11. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.expandopanel.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (383 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.expandopanel.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 3230
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"3230-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (3230 bytes)
          /**
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           * @author Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///selectable list widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          
          /**
           * expando panel widget
           */
          $.widget("ui.expandopanel",{
          	/**
          	 * Default values go here
          	 */
          	options: {
          			open: true,
          			togglerClass: "dc-toggler",
          			togglerClassClose: "dc-toggler-close",
          			title: null,
          			headerClass: "segment-header",
          			contentClass: "segment-content",
          	},
          	
          	_header: null,
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		var options = this.options;
          		var togglerClass = options.togglerClass;
          		var clearFixClass = "clearfix";
          		
          		//add children if none are defined in html
          		while($(this.element).children().size() < 2){
          			$(this.element).append(document.createElement("div"));
          		};
          		
          		this._header = $(this.element).children().first();
          		var content = $(this.element).children().last();
          		var title = options.title;
          		
           		//set the title if not null
          		if(title != null){
          			this._header.html(title);
          		}
          		
          		//add toggle button
          		if($("."+togglerClass,this.element).size() == 0){
          			this._header.append("<a class='"+togglerClass+"'></a>");
          		}
          		
          		var toggler = this._header.children().first();
          		
          		//style the header
          		this._header.addClass(options.headerClass);
          		this._header.addClass(options.clearfix);
          		
          		
          		//add toggle to the header 
          		this._header.click(function(evt){
          			toggler.toggleClass(options.togglerClassClose);
          			content.slideToggle("fast");
          		});
          		
          		//style the content 
          		content.addClass(options.contentClass);
          		content.addClass(options.clearfix);
          
          		if(!options.open){
          			content.css("display", "none");
                      toggler.toggleClass(options.togglerClassClose);
          		}
          
          	},
          	
          	toggle: function(){
          	    $(this._header).trigger("click");
          	},
          	
          	getContent: function(){
          		return $(this.element).children().last();
          	},
          	
          	append: function(/*dom node*/ node){
          		this.getContent().append(node);
          	},
          });
          
          /**
           * Tabular Expando Panel: used for displaying lists of static properties
           */
          $.widget("ui.tabularexpandopanel", 
          	$.extend({}, $.ui.expandopanel.prototype, 
          		{  //extended definition 
          			_init: function(){ 
          				$.ui.expandopanel.prototype._init.call(this); //call super init first
          				//add the table if it is not null
          				var d = this.options.data;
          				this.setData(d);
          			}, 
          
          			setData: function(data){ 
          				var tableClass = "ui-tabularexpandopanel-table";
          				$("."+tableClass, this.element).remove();
          				if(data != null){
          					var table = dc.createTable(data, ["label", "value"]);
          					$(table).addClass(tableClass)
          					        .attr("role", "presentation");
          
          					this.append(table);
          				}
          
          			}, 
          
          			destroy: function(){ 
          				//tabular destroy here
          				$.ui.expandopanel.prototype.destroy.call(this); // call the original function 
          			}, 
          			
          			options: $.extend({}, $.ui.expandopanel.prototype.options, {
          				data: [],  //2 dimensional array
          			}),
          		}
          	)
          ); 
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        12. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.listdetailviewer.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (387 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.listdetailviewer.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 2185
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"2185-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (2185 bytes)
          /**
           * This jquery plugin combines a selectablelist with a "detail" pane.
           * created by Daniel Bernstein
           */
          $.widget("ui.listdetailviewer", 
          	{  
          		_init: function(){ 
          			var that = this;
          			var o = this.options;
          			//reference the selectablelist if it exists
          			var list = $("#"+o.selectableListId).first();
          			if(list == null || list == undefined){
          				list = $.fn.create("div").attr("id", o.selectableListId);
          				$(this.element).append(list);
          			}
          
          			var dt = $("#"+o.detailId).first();
          			if(dt == null || dt == undefined){
          				dt = $.fn.create("div").attr("id", o.detailId);
          				$(this.element).append(detail);
          			}
          			
          			
          			//initialize list
          			list.selectablelist({ selectable: false })
          				.bind("currentItemChanged", function(evt, state){
          					var currentItem = state.currentItem;
          					if(currentItem == null){
          						that._showNoSelection();
          					}else{
          						var data = currentItem.data;
          						if(data == null || data == undefined){
          							that._showNoSelection();
          						}else{
          							var detail = that._prepareDetail(data);
          							that._getDetail().replaceContents(detail,o.detailLayout);
          						}
          					}
          				});
          			
          		}, 
          		
          		destroy: function(){ 
          
          		}, 
          		
          		options: {
          				selectableListId: "selectable-list"
          			,	detailId:  "list-detail"
          			,   detailClass: "dc-detail"
          			,   detailPreparer: function(data){
          					 var that = this;
          					 var detail = $.fn.create("div");
          					 var proplist = $.fn.create("table");
          					 detail.append(proplist);
          					 for(i in data){
          						 proplist.append(
          							 $.fn.create("tr")
          							 	.append($.fn.create("td").html(i))
          							 	.append($.fn.create("td").html(data[i]))
          						 );
          					 }
          					 
          					 return detail;
          				}
          		},
          		
          		//default behavior removes the children
          		_showNoSelection: function(){
          			this._clearDetail();
          		},
          		
          		_clearDetail: function(){
          			 $("#"+this.options.detailId, this.element)
          				.children().remove();			
          			
          		},
          		
          		_getDetail: function(){
          			 return $("#"+this.options.detailId, this.element);
          		},
          		
          		
          		//load detail
          		//default behavior: iterator through members and write them to an table
          		_prepareDetail: function(data){
          			return this.options.detailPreparer(data);
          		},
          	}
          );
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        13. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.onoffswitch.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (382 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.onoffswitch.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 3055
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"3055-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (3055 bytes)
          /**
           * created by Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///on off switch  widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          $.widget("ui.onoffswitch",{
          	/**
          	 * Default values go here
          	 */
          	options: {
                initialState: "on"
          		, onStateClass: "on left"
          		, onIconClass: "unlock"
          		, offStateClass: "off right"
          		, offIconClass: "lock"
          		, onText: "On"
          		, offText: "Off"
          		, readOnly: false
          	},
          	
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		//clear the element state
          		$(that.element).html("");
          		var o = this.options;
          		var leftButtonOnState = this._createButton(o.onText, o.onStateClass, o.onIconClass, false, o.readOnly);
          		var rightButtonOnState = this._createButton(o.offText, o.offStateClass, o.offIconClass, true, o.readOnly);
          		var leftButtonOffState = this._createButton(o.onText, o.onStateClass, o.onIconClass, true, o.readOnly);
          		var rightButtonOffState = this._createButton(o.offText, o.offStateClass, o.offIconClass, false, o.readOnly);
          		
          		rightButtonOnState.click(function(evt){
          			evt.preventDefault();
          			that._fireOffEvent();
          		});
          		
          		var onState = $.fn.create("span")
          							.addClass("button-holder")
          							.addClass("button-holder-on")
          							.append(leftButtonOnState)
          							.append(rightButtonOnState);
          		
          		$(this.element).append(onState);
          
          
          		leftButtonOffState.click(function(evt){
          			evt.preventDefault();
          			that._fireOnEvent(evt);
          		});
          		var offState = $.fn.create("span")
          							.addClass("button-holder")
          							.addClass("button-holder-off")
          							.append(leftButtonOffState)
          							.append(rightButtonOffState);
          		$(this.element).append(offState);
          
          		
          		this._switch(o.initialState);
          	},
          	
          	_fireOnEvent: function(evt){
          		var that = this;
          		this.element.trigger("turnOn", {
          			success:function(evt){ 
          				that._switch("on")
          			},
          			
          			failure: function(evt){
          				alert("no turn on failure handler defined");
          			},
          		});
          	},
          
          	_fireOffEvent: function(){
          		var that = this;
          		this.element.trigger("turnOff", {
          			success:function(evt){ 
          				that._switch("off")
          			},
          			
          			failure: function(evt){
          				alert("no turn offfailure handler defined");
          			},
          		});
          	},
          
          	_switch: function(state){
          		$(".button-holder", this.element).css("display","none");
          
          		if(state =="on"){
          			$(".button-holder-on", this.element).css("display","inline-block");
          		}else{
          			$(".button-holder-off", this.element).css("display","inline-block");
          		}
          	},
          	
          	on: function(){
          		this._switch("on");
          		this._fireOnEvent();
          	},
          	
          	_createButton: function(text, stateClass, iconClass, clickable, readOnly)
          	{
          		var button;
          		var icon = $.fn.create("i")
          			.addClass("pre")
          			.addClass(iconClass);
          		if (clickable) {
          			button = $.fn.create("button");
          		} else {
          			button = $.fn.create("span");	
          		}
          		button
          			.addClass("switch")
          			.addClass(stateClass) // need to change to be "left" for on, "right" for off
          			.append(icon)
          			.append(text)
          		    .disable(readOnly);
          		return button;
          	}
          });
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        14. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (385 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 11271
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"11271-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (11271 bytes)
          /**
           * 
           * created by Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///selectable list widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          (function(){
          /**
           * Selectable list widget
           */
          $.widget("ui.selectablelist",{
          	
          	/**
          	 * Default values go here
          	 */
          	options: {
          	
          			itemClass: "dc-item"
          		,   selectable: true
          		,   clickable: true
          		,   itemActionClass: "dc-action-panel"
          			
          	},
          	
          	_currentItem: null,
          	_footer: null,
          	dataMap: new Array(),
          	
          	_restyleSiblings: function(siblings){
          		siblings.removeClass("dc-selected-list-item dc-checked-selected-list-item dc-checked-list-item");
          		siblings.find("input[type='checkbox']:checked").closest("." +this.options.itemClass).addClass("dc-checked-list-item");
          	},
          	
          	_styleItem:  function(target){
          		if(target != undefined && target != null){
          			var item = $(target).nearestOfClass(this.options.itemClass);
          			$(item).removeClass("dc-checked-selected-list-item dc-checked-list-item dc-selected-list-item");
          			var checked = $(item).find("input[type='checkbox']:checked").size() > 0;
          			$(item).addClass(checked ? "dc-checked-selected-list-item" : "dc-selected-list-item");
          			this._restyleSiblings(item.siblings());
          		}else{
          			this._restyleSiblings(this.element.children("."+this.options.itemClass));
          		}
          		
          	},
          
          	_getSelectedItems: function(){
          		var array =  new Array();
          		var items = this.element.find("."+this.options.itemClass).toArray();
          		$.each(items, function(i, e){
          			if($(e).find("input[type='checkbox']:checked").size() > 0){
          				array.push(e);
          			}
          		});
          
          		return array;
          	},
          	
          	getSelectedData: function(){
          		var that = this;
          		var selected = this._getSelectedItems();
          		var selectedData = new Array();
          		$.each(selected, function(i,selectedItem){
          			selectedData.push(that._getDataById($(selectedItem).attr("id")));
          		});
          		
          		return selectedData;
          	},
          	
          	_setCurrentItem: function(item){
              this._currentItem = {
                                   item:item, 
                                   data: this._getDataById($(item).attr("id")),
                                 };
          	},
          	
          	_fireCurrentItemChanged: function(item, notify){
          		
          		if(item != null){
          		  this._setCurrentItem(item);
          		}else{
          			this._currentItem = null;
          		}
          		
          		
          		$("input[type='checkbox']:checked",this.element).removeAttr("checked");
          		this._styleItem(item);
          		if(item){
          		    $(item).find("input[type='checkbox']")
          		           .not("[disabled]")
          		           .attr("checked",true);
          		}
          
                  var selectedItems = this._getSelectedItems();
          		
          		var fire = (notify == undefined || notify == null || notify == true);
          		if(fire){
          			this.element.trigger(
          				"currentItemChanged",
          				{	
          					currentItem:this._currentItem, 
          					selectedItems: selectedItems
          				}
          			);
          		}
          	},
          	
          	_fireSelectionChanged: function(){
          	  var selectedItems = this._getSelectedItems();
              
          		if(selectedItems.length == 0){
          		    this._fireCurrentItemChanged(null, false);
          		}else if(selectedItems.length == 1){
          		 this._currentItem = this._setCurrentItem(selectedItems[0]);
          		}
          		
          		var ci = this._currentItem;
              this._styleItem(ci != null && ci.item != null ? ci.item : null);
              
          		
          		this.element.trigger(
          			"selectionChanged", 
          			{
          				selectedItems: this._getSelectedItems(), 
          				currentItem: this._currentItem,
          			}
          		);
          	},
          
          	_fireItemRemoved: function(item, data){
          		this.element.trigger(
          		  "itemRemoved", 
          		  {
          		      item: item,
          		      data: data,
          		  }
          	    );
          	},
          
          
          
          	_itemSelectionStateChanged: function(target){
          		var item = $(target).closest("."+this.options.itemClass);
          		this._fireSelectionChanged(item);
          	},
          	
          	clear: function(notify){
          		this._currentItem = null;
          		this.element.children("."+this.options.itemClass).remove();	
                  this.element.children("."+this.options.itemClass + "-divider").remove(); 
          		this.dataMap = new Array();
          		this._fireCurrentItemChanged(null,notify);
          		$(this._footer).html('');
          	},
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		this.clear(false);
          
          		this._footer = $.fn.create("div").addClass("dc-selectablelist-footer").html("");
          		$(that.element).append(that._footer);
          		
          		//add item classes to all direct children
          		$(that.element).children("."+this.options.itemClass).each(function(i,c){
          			that._initItem(c);
          		});
          		
          		that.element.unbind().bind("selectionChanged", function(evt, state){
          			var selectionChanged = that.options.selectionChanged;
          			if(selectionChanged){
          				selectionChanged(evt,state);
          			}
          		});
          		
          	},
          	
          
              	addItem : function(item, 
              	                   data, 
              	                   selected, 
              	                   /* optional boolean */disabled, 
              	                   /*optional boolean*/noIndent, //suppresses indentation for non-selectable items.
              	                   /*optional String*/ dividerLabel //specifies label of the section 
              	                                                    //into which the item should be inserted.
              	                   ) {
              	var that = this;
                this.setFooter('');
                if(dividerLabel){
                  var dividers = [];
                  $("." + this.itemDividerClass(), this.element).each(function(i,e){
                      dividers.push(e);
                  });
                  
                  if(dividers.length > 0){
                    
                    $.each(dividers, function(i, div){
                      if($(div).html() == dividerLabel){
                         if(i == dividers.length-1){
                           that._footer.before(item);
                         }else{
                           $(dividers[i+1]).before(item);
                         }
                         
                         return false;
                      }
                    });
                  }else{
                    this._footer.before(item);
                  }
                
          
                  if (selected && this.options.selectable) {
                    $("input[type=checkbox]", item).attr("checked", true);
                  }
                  
                }else{
                    this._footer.before(item);
                }
          
                this._initItem(item, data, disabled, noIndent);
          
                return item;
              },
              
              itemDividerClass: function(){
                return this.options.itemClass+"-divider";
              },
          	
              addDivider: function(label){
                  this.setFooter('');
                  
                  var divider = $.fn.create("div").addClass(this.itemDividerClass());
                  divider.html(label);
                  this._footer.before(divider);
              },
          	
          	select: function(select){
          		var that = this;
          		that._select(select);
          		that._fireSelectionChanged();
          	},
          
              _select: function(select){
                  var that = this;
                  $("input[type=checkbox]",this.element).not("[disabled]").attr("checked",select);
              },
          
          	removeById: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		var data = this._removeDataById(elementId);
          		item.remove();
          		
          		if(this._currentItem){
          		    if($(this._currentItem.item).attr("id") == elementId){
          	            this._fireCurrentItemChanged(null);
          		    }
          		}
          		this._fireItemRemoved(item, data);
          	},
          
          	idExists: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		if(item){
          			return true;
          		}else{
          			return false;
          		}
          	},
          
          
          	_getDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_removeDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				this.dataMap.splice(i,1);
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_putData: function(id,data){
          		this.dataMap[this.dataMap.length] = { key: id, value: data};
          	},
          	
          	setCurrentItemById: function(id, notify){
          	    if(this._currentItem){
          	        if(this._currentItem.item.attr("id") == id){
          	            return;
          	        }
          	    }
          		this._fireCurrentItemChanged($("#"+id, this.element), notify);
          	},
          	
          	setFirstItemAsCurrent: function(){
          		 var first = this.element.children("."+this.options.itemClass).first();
          		 if(first != undefined && first !=null){
          			 this._fireCurrentItemChanged(first, true);
          		 }
          	},
          
          	lastItemData: function(){
          		 var last = this.lastItem();
          		 if(last != undefined && last != null){
          			 return this._getDataById($(last).attr("id"));
          		 }
          		 return null;
          	},
          	
          	lastItem: function(){
          		 return this.element.children("."+this.options.itemClass).last();
          	},
          
          	length: function(){
          		 return this.element.children("."+this.options.itemClass).size();
          	},
          
          	
          	currentItem:function(){
          		return this._currentItem;
          	},
          	
          	setFooter:function(footerContent){
          		this._footer.html('');
          		$(this._footer).append(footerContent);
          	},
          
          	_initItem : function(item, data, selectionDisabled, noIndent) {
                var that = this;
                var o = this.options;
                var itemClass = o.itemClass;
                var actionClass = o.itemActionClass;
                var checkbox;
                var checkboxHolder;
          
                if (selectionDisabled == undefined || selectionDisabled == null) {
                  selectionDisabled = false;
                }
          
                $(item).addClass(itemClass);
          
                if (this.options.selectable && !(selectionDisabled && noIndent)) {
                  var checkbox = $("<input type='checkbox'/>");
                  checkbox.attr("aria-labelledby", item.attr("id"));
                  //checkbox holder serves to create a clickable
                  //buffer zone around the checkbox in order to
                  //make it easier for the user to check.
                  var checkboxHolder = $("<span class='cb-holder'></span>");
                  checkboxHolder.append(checkbox);
                  $(item).prepend(checkboxHolder);
          
                  if (selectionDisabled != undefined) {
                    checkbox.disable(selectionDisabled);
                    if (selectionDisabled) {
                      checkbox.makeHidden();
                    } else {
                      checkboxHolder.click(function(evt) {
                        if (evt.target == this) {
                          if (checkbox.is(":checked")) {
                            checkbox.removeAttr("checked");
                          } else {
                            checkbox.attr("checked", "checked");
                          }
                          that._itemSelectionStateChanged(checkbox);
                        }
                        evt.stopPropagation();
                      });
                    }
                  }
          
                  $(item).children().first().change(function(evt) {
                    that._itemSelectionStateChanged(evt.target);
                    evt.stopPropagation();
                  });
                }
          
                $(item).children("div").last().addClass("float-r").addClass(actionClass);
          
                var clickHandler = function(evt) {
                  var item = $(evt.target).nearestOfClass(itemClass);
                  if ($(evt.target).attr("type") != "checkbox") {
          
                    if (that.options.clickable) {
                      if (that.options.selectable) {
                        that._select(false);
                        item.find(":checkbox").not("[disabled]").attr("checked", true);
                      }
          
                      that._fireCurrentItemChanged(item);
                    }
          
                    evt.stopPropagation();
                  }
                };
          
                //bind mouse action listeners
                $(item).find("." + actionClass).andSelf().click(clickHandler).dblclick(clickHandler).mouseover(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeVisible();
                }).mouseout(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeHidden();
                });
          
                //hide all actions to start
                $(item).find("." + actionClass).makeHidden();
          
                //add the data to the map
                that._putData($(item).attr("id"), data);
                return item;
              }
          });
          
          })();
          
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        15. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        16. GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (368 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 93868
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"93868-1329845124000"
          Last-Modified: Tue, 21 Feb 2012 17:25:24 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (93868 bytes)
          /*! jQuery v1.7.1 jquery.com | jquery.org/license */
          (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
          f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.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(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
          {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        17. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (397 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 37133
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"37133-1268175436000"
          Last-Modified: Tue, 09 Mar 2010 22:57:16 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (37133 bytes)
          /*
           * jQuery validation plug-in 1.7
           *
           * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
           * http://docs.jquery.com/Plugins/Validation
           *
           * Copyright (c) 2006 - 2008 Jörn Zaefferer
           *
           * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          $.extend($.fn, {
          	// http://docs.jquery.com/Plugins/Validation/validate
          	validate: function( options ) {
          
          		// if nothing is selected, return nothing; can't chain anyway
          		if (!this.length) {
          			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
          			return;
          		}
          
          		// check if a validator for this form was already created
          		var validator = $.data(this[0], 'validator');
          		if ( validator ) {
          			return validator;
          		}
          		
          		validator = new $.validator( options, this[0] );
          		$.data(this[0], 'validator', validator); 
          		
          		if ( validator.settings.onsubmit ) {
          		
          			// allow suppresing validation by adding a cancel class to the submit button
          			this.find("input, button").filter(".cancel").click(function() {
          				validator.cancelSubmit = true;
          			});
          			
          			// when a submitHandler is used, capture the submitting button
          			if (validator.settings.submitHandler) {
          				this.find("input, button").filter(":submit").click(function() {
          					validator.submitButton = this;
          				});
          			}
          		
          			// validate the form on submit
          			this.submit( function( event ) {
          				if ( validator.settings.debug )
          					// prevent form submit to be able to see console output
          					event.preventDefault();
          					
          				function handle() {
          					if ( validator.settings.submitHandler ) {
          						if (validator.submitButton) {
          							// insert a hidden input as a replacement for the missing submit button
          							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
          						}
          						validator.settings.submitHandler.call( validator, validator.currentForm );
          						if (validator.submitButton) {
          							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
          							hidden.remove();
          						}
          						return false;
          					}
          					return true;
          				}
          					
          				// prevent submit for invalid forms or custom submit handlers
          				if ( validator.cancelSubmit ) {
          					validator.cancelSubmit = false;
          					return handle();
          				}
          				if ( validator.form() ) {
          					if ( validator.pendingRequest ) {
          						validator.formSubmitted = true;
          						return false;
          					}
          					return handle();
          				} else {
          					validator.focusInvalid();
          					return false;
          				}
          			});
          		}
          		
          		return validator;
          	},
          	// http://docs.jquery.com/Plugins/Validation/valid
          	valid: function() {
                  if ( $(this[0]).is('form')) {
                      return this.validate().form();
                  } else {
                      var valid = true;
                      var validator = $(this[0].form).validate();
                      this.each(function() {
          				valid &= validator.element(this);
                      });
                      return valid;
                  }
              },
          	// attributes: space seperated list of attributes to retrieve and remove
          	removeAttrs: function(attributes) {
          		var result = {},
          			$element = this;
          		$.each(attributes.split(/\s/), function(index, value) {
          			result[value] = $element.attr(value);
          			$element.removeAttr(value);
          		});
          		return result;
          	},
          	// http://docs.jquery.com/Plugins/Validation/rules
          	rules: function(command, argument) {
          		var element = this[0];
          		
          		if (command) {
          			var settings = $.data(element.form, 'validator').settings;
          			var staticRules = settings.rules;
          			var existingRules = $.validator.staticRules(element);
          			switch(command) {
          			case "add":
          				$.extend(existingRules, $.validator.normalizeRule(argument));
          				staticRules[element.name] = existingRules;
          				if (argument.messages)
          					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
          				break;
          			case "remove":
          				if (!argument) {
          					delete staticRules[element.name];
          					return existingRules;
          				}
          				var filtered = {};
          				$.each(argument.split(/\s/), function(index, method) {
          					filtered[method] = existingRules[method];
          					delete existingRules[method];
          				});
          				return filtered;
          			}
          		}
          		
          		var data = $.validator.normalizeRules(
          		$.extend(
          			{},
          			$.validator.metadataRules(element),
          			$.validator.classRules(element),
          			$.validator.attributeRules(element),
          			$.validator.staticRules(element)
          		), element);
          		
          		// make sure required is at front
          		if (data.required) {
          			var param = data.required;
          			delete data.required;
          			data = $.extend({required: param}, data);
          		}
          		
          		return data;
          	}
          });
          
          // Custom selectors
          $.extend($.expr[":"], {
          	// http://docs.jquery.com/Plugins/Validation/blank
          	blank: function(a) {return !$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/filled
          	filled: function(a) {return !!$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/unchecked
          	unchecked: function(a) {return !a.checked;}
          });
          
          // constructor for validator
          $.validator = function( options, form ) {
          	this.settings = $.extend( true, {}, $.validator.defaults, options );
          	this.currentForm = form;
          	this.init();
          };
          
          $.validator.format = function(source, params) {
          	if ( arguments.length == 1 ) 
          		return function() {
          			var args = $.makeArray(arguments);
          			args.unshift(source);
          			return $.validator.format.apply( this, args );
          		};
          	if ( arguments.length > 2 && params.constructor != Array  ) {
          		params = $.makeArray(arguments).slice(1);
          	}
          	if ( params.constructor != Array ) {
          		params = [ params ];
          	}
          	$.each(params, function(i, n) {
          		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
          	});
          	return source;
          };
          
          $.extend($.validator, {
          	
          	defaults: {
          		messages: {},
          		groups: {},
          		rules: {},
          		errorClass: "error",
          		validClass: "valid",
          		errorElement: "label",
          		focusInvalid: true,
          		errorContainer: $( [] ),
          		errorLabelContainer: $( [] ),
          		onsubmit: true,
          		ignore: [],
          		ignoreTitle: false,
          		onfocusin: function(element) {
          			this.lastActive = element;
          				
          			// hide error label and remove error class on focus if enabled
          			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
          				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
          				this.errorsFor(element).hide();
          			}
          		},
          		onfocusout: function(element) {
          			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
          				this.element(element);
          			}
          		},
          		onkeyup: function(element) {
          			if ( element.name in this.submitted || element == this.lastElement ) {
          				this.element(element);
          			}
          		},
          		onclick: function(element) {
          			// click on selects, radiobuttons and checkboxes
          			if ( element.name in this.submitted )
          				this.element(element);
          			// or option elements, check parent select in that case
          			else if (element.parentNode.name in this.submitted)
          				this.element(element.parentNode);
          		},
          		highlight: function( element, errorClass, validClass ) {
          			$(element).addClass(errorClass).removeClass(validClass);
          		},
          		unhighlight: function( element, errorClass, validClass ) {
          			$(element).removeClass(errorClass).addClass(validClass);
          		}
          	},
          
          	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
          	setDefaults: function(settings) {
          		$.extend( $.validator.defaults, settings );
          	},
          
          	messages: {
          		required: "This field is required.",
          		remote: "Please fix this field.",
          		email: "Please enter a valid email address.",
          		url: "Please enter a valid URL.",
          		date: "Please enter a valid date.",
          		dateISO: "Please enter a valid date (ISO).",
          		number: "Please enter a valid number.",
          		digits: "Please enter only digits.",
          		creditcard: "Please enter a valid credit card number.",
          		equalTo: "Please enter the same value again.",
          		accept: "Please enter a value with a valid extension.",
          		maxlength: $.validator.format("Please enter no more than {0} characters."),
          		minlength: $.validator.format("Please enter at least {0} characters."),
          		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
          		range: $.validator.format("Please enter a value between {0} and {1}."),
          		max: $.validator.format("Please enter a value less than or equal to {0}."),
          		min: $.validator.format("Please enter a value greater than or equal to {0}.")
          	},
          	
          	autoCreateRanges: false,
          	
          	prototype: {
          		
          		init: function() {
          			this.labelContainer = $(this.settings.errorLabelContainer);
          			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
          			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
          			this.submitted = {};
          			this.valueCache = {};
          			this.pendingRequest = 0;
          			this.pending = {};
          			this.invalid = {};
          			this.reset();
          			
          			var groups = (this.groups = {});
          			$.each(this.settings.groups, function(key, value) {
          				$.each(value.split(/\s/), function(index, name) {
          					groups[name] = key;
          				});
          			});
          			var rules = this.settings.rules;
          			$.each(rules, function(key, value) {
          				rules[key] = $.validator.normalizeRule(value);
          			});
          			
          			function delegate(event) {
          				var validator = $.data(this[0].form, "validator"),
          					eventType = "on" + event.type.replace(/^validate/, "");
          				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
          			}
          			$(this.currentForm)
          				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
          				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);
          
          			if (this.settings.invalidHandler)
          				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/form
          		form: function() {
          			this.checkForm();
          			$.extend(this.submitted, this.errorMap);
          			this.invalid = $.extend({}, this.errorMap);
          			if (!this.valid())
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          			this.showErrors();
          			return this.valid();
          		},
          		
          		checkForm: function() {
          			this.prepareForm();
          			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
          				this.check( elements[i] );
          			}
          			return this.valid(); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/element
          		element: function( element ) {
          			element = this.clean( element );
          			this.lastElement = element;
          			this.prepareElement( element );
          			this.currentElements = $(element);
          			var result = this.check( element );
          			if ( result ) {
          				delete this.invalid[element.name];
          			} else {
          				this.invalid[element.name] = true;
          			}
          			if ( !this.numberOfInvalids() ) {
          				// Hide error containers on last error
          				this.toHide = this.toHide.add( this.containers );
          			}
          			this.showErrors();
          			return result;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
          		showErrors: function(errors) {
          			if(errors) {
          				// add items to error list and map
          				$.extend( this.errorMap, errors );
          				this.errorList = [];
          				for ( var name in errors ) {
          					this.errorList.push({
          						message: errors[name],
          						element: this.findByName(name)[0]
          					});
          				}
          				// remove items from success list
          				this.successList = $.grep( this.successList, function(element) {
          					return !(element.name in errors);
          				});
          			}
          			this.settings.showErrors
          				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
          				: this.defaultShowErrors();
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
          		resetForm: function() {
          			if ( $.fn.resetForm )
          				$( this.currentForm ).resetForm();
          			this.submitted = {};
          			this.prepareForm();
          			this.hideErrors();
          			this.elements().removeClass( this.settings.errorClass );
          		},
          		
          		numberOfInvalids: function() {
          			return this.objectLength(this.invalid);
          		},
          		
          		objectLength: function( obj ) {
          			var count = 0;
          			for ( var i in obj )
          				count++;
          			return count;
          		},
          		
          		hideErrors: function() {
          			this.addWrapper( this.toHide ).hide();
          		},
          		
          		valid: function() {
          			return this.size() == 0;
          		},
          		
          		size: function() {
          			return this.errorList.length;
          		},
          		
          		focusInvalid: function() {
          			if( this.settings.focusInvalid ) {
          				try {
          					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
          					.filter(":visible")
          					.focus()
          					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
          					.trigger("focusin");
          				} catch(e) {
          					// ignore IE throwing errors when focusing hidden elements
          				}
          			}
          		},
          		
          		findLastActive: function() {
          			var lastActive = this.lastActive;
          			return lastActive && $.grep(this.errorList, function(n) {
          				return n.element.name == lastActive.name;
          			}).length == 1 && lastActive;
          		},
          		
          		elements: function() {
          			var validator = this,
          				rulesCache = {};
          			
          			// select all valid inputs inside the form (no submit or reset buttons)
          			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
          			return $([]).add(this.currentForm.elements)
          			.filter(":input")
          			.not(":submit, :reset, :image, [disabled]")
          			.not( this.settings.ignore )
          			.filter(function() {
          				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
          			
          				// select only the first element for each name, and only those with rules specified
          				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
          					return false;
          				
          				rulesCache[this.name] = true;
          				return true;
          			});
          		},
          		
          		clean: function( selector ) {
          			return $( selector )[0];
          		},
          		
          		errors: function() {
          			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
          		},
          		
          		reset: function() {
          			this.successList = [];
          			this.errorList = [];
          			this.errorMap = {};
          			this.toShow = $([]);
          			this.toHide = $([]);
          			this.currentElements = $([]);
          		},
          		
          		prepareForm: function() {
          			this.reset();
          			this.toHide = this.errors().add( this.containers );
          		},
          		
          		prepareElement: function( element ) {
          			this.reset();
          			this.toHide = this.errorsFor(element);
          		},
          	
          		check: function( element ) {
          			element = this.clean( element );
          			
          			// if radio/checkbox, validate first element in group instead
          			if (this.checkable(element)) {
          				element = this.findByName( element.name )[0];
          			}
          			
          			var rules = $(element).rules();
          			var dependencyMismatch = false;
          			for( method in rules ) {
          				var rule = { method: method, parameters: rules[method] };
          				try {
          					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
          					
          					// if a method indicates that the field is optional and therefore valid,
          					// don't mark it as valid when there are no other rules
          					if ( result == "dependency-mismatch" ) {
          						dependencyMismatch = true;
          						continue;
          					}
          					dependencyMismatch = false;
          					
          					if ( result == "pending" ) {
          						this.toHide = this.toHide.not( this.errorsFor(element) );
          						return;
          					}
          					
          					if( !result ) {
          						this.formatAndAdd( element, rule );
          						return false;
          					}
          				} catch(e) {
          					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
          						 + ", check the '" + rule.method + "' method", e);
          					throw e;
          				}
          			}
          			if (dependencyMismatch)
          				return;
          			if ( this.objectLength(rules) )
          				this.successList.push(element);
          			return true;
          		},
          		
          		// return the custom message for the given element and validation method
          		// specified in the element's "messages" metadata
          		customMetaMessage: function(element, method) {
          			if (!$.metadata)
          				return;
          			
          			var meta = this.settings.meta
          				? $(element).metadata()[this.settings.meta]
          				: $(element).metadata();
          			
          			return meta && meta.messages && meta.messages[method];
          		},
          		
          		// return the custom message for the given element name and validation method
          		customMessage: function( name, method ) {
          			var m = this.settings.messages[name];
          			return m && (m.constructor == String
          				? m
          				: m[method]);
          		},
          		
          		// return the first defined argument, allowing empty strings
          		findDefined: function() {
          			for(var i = 0; i < arguments.length; i++) {
          				if (arguments[i] !== undefined)
          					return arguments[i];
          			}
          			return undefined;
          		},
          		
          		defaultMessage: function( element, method) {
          			return this.findDefined(
          				this.customMessage( element.name, method ),
          				this.customMetaMessage( element, method ),
          				// title is never undefined, so handle empty string as undefined
          				!this.settings.ignoreTitle && element.title || undefined,
          				$.validator.messages[method],
          				"<strong>Warning: No message defined for " + element.name + "</strong>"
          			);
          		},
          		
          		formatAndAdd: function( element, rule ) {
          			var message = this.defaultMessage( element, rule.method ),
          				theregex = /\$?\{(\d+)\}/g;
          			if ( typeof message == "function" ) {
          				message = message.call(this, rule.parameters, element);
          			} else if (theregex.test(message)) {
          				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
          			}			
          			this.errorList.push({
          				message: message,
          				element: element
          			});
          			
          			this.errorMap[element.name] = message;
          			this.submitted[element.name] = message;
          		},
          		
          		addWrapper: function(toToggle) {
          			if ( this.settings.wrapper )
          				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
          			return toToggle;
          		},
          		
          		defaultShowErrors: function() {
          			for ( var i = 0; this.errorList[i]; i++ ) {
          				var error = this.errorList[i];
          				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
          				this.showLabel( error.element, error.message );
          			}
          			if( this.errorList.length ) {
          				this.toShow = this.toShow.add( this.containers );
          			}
          			if (this.settings.success) {
          				for ( var i = 0; this.successList[i]; i++ ) {
          					this.showLabel( this.successList[i] );
          				}
          			}
          			if (this.settings.unhighlight) {
          				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
          					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
          				}
          			}
          			this.toHide = this.toHide.not( this.toShow );
          			this.hideErrors();
          			this.addWrapper( this.toShow ).show();
          		},
          		
          		validElements: function() {
          			return this.currentElements.not(this.invalidElements());
          		},
          		
          		invalidElements: function() {
          			return $(this.errorList).map(function() {
          				return this.element;
          			});
          		},
          		
          		showLabel: function(element, message) {
          			var label = this.errorsFor( element );
          			if ( label.length ) {
          				// refresh error/success class
          				label.removeClass().addClass( this.settings.errorClass );
          			
          				// check if we have a generated label, replace the message then
          				label.attr("generated") && label.html(message);
          			} else {
          				// create label
          				label = $("<" + this.settings.errorElement + "/>")
          					.attr({"for":  this.idOrName(element), generated: true})
          					.addClass(this.settings.errorClass)
          					.html(message || "");
          				if ( this.settings.wrapper ) {
          					// make sure the element is visible, even in IE
          					// actually showing the wrapped element is handled elsewhere
          					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
          				}
          				if ( !this.labelContainer.append(label).length )
          					this.settings.errorPlacement
          						? this.settings.errorPlacement(label, $(element) )
          						: label.insertAfter(element);
          			}
          			if ( !message && this.settings.success ) {
          				label.text("");
          				typeof this.settings.success == "string"
          					? label.addClass( this.settings.success )
          					: this.settings.success( label );
          			}
          			this.toShow = this.toShow.add(label);
          		},
          		
          		errorsFor: function(element) {
          			var name = this.idOrName(element);
              		return this.errors().filter(function() {
          				return $(this).attr('for') == name;
          			});
          		},
          		
          		idOrName: function(element) {
          			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
          		},
          
          		checkable: function( element ) {
          			return /radio|checkbox/i.test(element.type);
          		},
          		
          		findByName: function( name ) {
          			// select by name and filter by form for performance over form.find("[name=...]")
          			var form = this.currentForm;
          			return $(document.getElementsByName(name)).map(function(index, element) {
          				return element.form == form && element.name == name && element  || null;
          			});
          		},
          		
          		getLength: function(value, element) {
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				return $("option:selected", element).length;
          			case 'input':
          				if( this.checkable( element) )
          					return this.findByName(element.name).filter(':checked').length;
          			}
          			return value.length;
          		},
          	
          		depend: function(param, element) {
          			return this.dependTypes[typeof param]
          				? this.dependTypes[typeof param](param, element)
          				: true;
          		},
          	
          		dependTypes: {
          			"boolean": function(param, element) {
          				return param;
          			},
          			"string": function(param, element) {
          				return !!$(param, element.form).length;
          			},
          			"function": function(param, element) {
          				return param(element);
          			}
          		},
          		
          		optional: function(element) {
          			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
          		},
          		
          		startRequest: function(element) {
          			if (!this.pending[element.name]) {
          				this.pendingRequest++;
          				this.pending[element.name] = true;
          			}
          		},
          		
          		stopRequest: function(element, valid) {
          			this.pendingRequest--;
          			// sometimes synchronization fails, make sure pendingRequest is never < 0
          			if (this.pendingRequest < 0)
          				this.pendingRequest = 0;
          			delete this.pending[element.name];
          			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
          				$(this.currentForm).submit();
          				this.formSubmitted = false;
          			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          				this.formSubmitted = false;
          			}
          		},
          		
          		previousValue: function(element) {
          			return $.data(element, "previousValue") || $.data(element, "previousValue", {
          				old: null,
          				valid: true,
          				message: this.defaultMessage( element, "remote" )
          			});
          		}
          		
          	},
          	
          	classRuleSettings: {
          		required: {required: true},
          		email: {email: true},
          		url: {url: true},
          		date: {date: true},
          		dateISO: {dateISO: true},
          		dateDE: {dateDE: true},
          		number: {number: true},
          		numberDE: {numberDE: true},
          		digits: {digits: true},
          		creditcard: {creditcard: true}
          	},
          	
          	addClassRules: function(className, rules) {
          		className.constructor == String ?
          			this.classRuleSettings[className] = rules :
          			$.extend(this.classRuleSettings, className);
          	},
          	
          	classRules: function(element) {
          		var rules = {};
          		var classes = $(element).attr('class');
          		classes && $.each(classes.split(' '), function() {
          			if (this in $.validator.classRuleSettings) {
          				$.extend(rules, $.validator.classRuleSettings[this]);
          			}
          		});
          		return rules;
          	},
          	
          	attributeRules: function(element) {
          		var rules = {};
          		var $element = $(element);
          		
          		for (method in $.validator.methods) {
          			var value = $element.attr(method);
          			if (value) {
          				rules[method] = value;
          			}
          		}
          		
          		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
          		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
          			delete rules.maxlength;
          		}
          		
          		return rules;
          	},
          	
          	metadataRules: function(element) {
          		if (!$.metadata) return {};
          		
          		var meta = $.data(element.form, 'validator').settings.meta;
          		return meta ?
          			$(element).metadata()[meta] :
          			$(element).metadata();
          	},
          	
          	staticRules: function(element) {
          		var rules = {};
          		var validator = $.data(element.form, 'validator');
          		if (validator.settings.rules) {
          			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
          		}
          		return rules;
          	},
          	
          	normalizeRules: function(rules, element) {
          		// handle dependency check
          		$.each(rules, function(prop, val) {
          			// ignore rule when param is explicitly false, eg. required:false
          			if (val === false) {
          				delete rules[prop];
          				return;
          			}
          			if (val.param || val.depends) {
          				var keepRule = true;
          				switch (typeof val.depends) {
          					case "string":
          						keepRule = !!$(val.depends, element.form).length;
          						break;
          					case "function":
          						keepRule = val.depends.call(element, element);
          						break;
          				}
          				if (keepRule) {
          					rules[prop] = val.param !== undefined ? val.param : true;
          				} else {
          					delete rules[prop];
          				}
          			}
          		});
          		
          		// evaluate parameters
          		$.each(rules, function(rule, parameter) {
          			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
          		});
          		
          		// clean number parameters
          		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
          			if (rules[this]) {
          				rules[this] = Number(rules[this]);
          			}
          		});
          		$.each(['rangelength', 'range'], function() {
          			if (rules[this]) {
          				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
          			}
          		});
          		
          		if ($.validator.autoCreateRanges) {
          			// auto-create ranges
          			if (rules.min && rules.max) {
          				rules.range = [rules.min, rules.max];
          				delete rules.min;
          				delete rules.max;
          			}
          			if (rules.minlength && rules.maxlength) {
          				rules.rangelength = [rules.minlength, rules.maxlength];
          				delete rules.minlength;
          				delete rules.maxlength;
          			}
          		}
          		
          		// To support custom messages in metadata ignore rule methods titled "messages"
          		if (rules.messages) {
          			delete rules.messages;
          		}
          		
          		return rules;
          	},
          	
          	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
          	normalizeRule: function(data) {
          		if( typeof data == "string" ) {
          			var transformed = {};
          			$.each(data.split(/\s/), function() {
          				transformed[this] = true;
          			});
          			data = transformed;
          		}
          		return data;
          	},
          	
          	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
          	addMethod: function(name, method, message) {
          		$.validator.methods[name] = method;
          		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
          		if (method.length < 3) {
          			$.validator.addClassRules(name, $.validator.normalizeRule(name));
          		}
          	},
          
          	methods: {
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/required
          		required: function(value, element, param) {
          			// check if dependency is met
          			if ( !this.depend(param, element) )
          				return "dependency-mismatch";
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				// could be an array for select-multiple or a string, both are fine this way
          				var val = $(element).val();
          				return val && val.length > 0;
          			case 'input':
          				if ( this.checkable(element) )
          					return this.getLength(value, element) > 0;
          			default:
          				return $.trim(value).length > 0;
          			}
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/remote
          		remote: function(value, element, param) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			
          			var previous = this.previousValue(element);
          			if (!this.settings.messages[element.name] )
          				this.settings.messages[element.name] = {};
          			previous.originalMessage = this.settings.messages[element.name].remote;
          			this.settings.messages[element.name].remote = previous.message;
          			
          			param = typeof param == "string" && {url:param} || param; 
          			
          			if ( previous.old !== value ) {
          				previous.old = value;
          				var validator = this;
          				this.startRequest(element);
          				var data = {};
          				data[element.name] = value;
          				$.ajax($.extend(true, {
          					url: param,
          					mode: "abort",
          					port: "validate" + element.name,
          					dataType: "json",
          					data: data,
          					success: function(response) {
          						validator.settings.messages[element.name].remote = previous.originalMessage;
          						var valid = response === true;
          						if ( valid ) {
          							var submitted = validator.formSubmitted;
          							validator.prepareElement(element);
          							validator.formSubmitted = submitted;
          							validator.successList.push(element);
          							validator.showErrors();
          						} else {
          							var errors = {};
          							var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
          							errors[element.name] = $.isFunction(message) ? message(value) : message;
          							validator.showErrors(errors);
          						}
          						previous.valid = valid;
          						validator.stopRequest(element, valid);
          					}
          				}, param));
          				return "pending";
          			} else if( this.pending[element.name] ) {
          				return "pending";
          			}
          			return previous.valid;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
          		minlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
          		maxlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
          		rangelength: function(value, element, param) {
          			var length = this.getLength($.trim(value), element);
          			return this.optional(element) || ( length >= param[0] && length <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/min
          		min: function( value, element, param ) {
          			return this.optional(element) || value >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/max
          		max: function( value, element, param ) {
          			return this.optional(element) || value <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/range
          		range: function( value, element, param ) {
          			return this.optional(element) || ( value >= param[0] && value <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/email
          		email: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
          			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/url
          		url: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
          			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
          		},
                  
          		// http://docs.jquery.com/Plugins/Validation/Methods/date
          		date: function(value, element) {
          			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
          		dateISO: function(value, element) {
          			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/number
          		number: function(value, element) {
          			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/digits
          		digits: function(value, element) {
          			return this.optional(element) || /^\d+$/.test(value);
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
          		// based on http://en.wikipedia.org/wiki/Luhn
          		creditcard: function(value, element) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			// accept only digits and dashes
          			if (/[^0-9-]+/.test(value))
          				return false;
          			var nCheck = 0,
          				nDigit = 0,
          				bEven = false;
          
          			value = value.replace(/\D/g, "");
          
          			for (var n = value.length - 1; n >= 0; n--) {
          				var cDigit = value.charAt(n);
          				var nDigit = parseInt(cDigit, 10);
          				if (bEven) {
          					if ((nDigit *= 2) > 9)
          						nDigit -= 9;
          				}
          				nCheck += nDigit;
          				bEven = !bEven;
          			}
          
          			return (nCheck % 10) == 0;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/accept
          		accept: function(value, element, param) {
          			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
          			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
          		equalTo: function(value, element, param) {
          			// bind to the blur event of the target in order to revalidate whenever the target field is updated
          			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
          			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
          				$(element).valid();
          			});
          			return value == target.val();
          		}
          		
          	}
          	
          });
          
          // deprecated, use $.validator.format instead
          $.format = $.validator.format;
          
          })(jQuery);
          
          // ajax mode: abort
          // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
          // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
          ;(function($) {
          	var ajax = $.ajax;
          	var pendingRequests = {};
          	$.ajax = function(settings) {
          		// create settings for compatibility with ajaxSetup
          		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
          		var port = settings.port;
          		if (settings.mode == "abort") {
          			if ( pendingRequests[port] ) {
          				pendingRequests[port].abort();
          			}
          			return (pendingRequests[port] = ajax.apply(this, arguments));
          		}
          		return ajax.apply(this, arguments);
          	};
          })(jQuery);
          
          // provides cross-browser focusin and focusout events
          // IE has native support, in other browsers, use event caputuring (neither bubbles)
          
          // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
          // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
          ;(function($) {
          	// only implement if not provided by jQuery core (since 1.4)
          	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
          	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
          		$.each({
          			focus: 'focusin',
          			blur: 'focusout'	
          		}, function( original, fix ){
          			$.event.special[fix] = {
          				setup:function() {
          					this.addEventListener( original, handler, true );
          				},
          				teardown:function() {
          					this.removeEventListener( original, handler, true );
          				},
          				handler: function(e) {
          					arguments[0] = $.event.fix(e);
          					arguments[0].type = fix;
          					return $.event.handle.apply(this, arguments);
          				}
          			};
          			function handler(e) {
          				e = $.event.fix(e);
          				e.type = fix;
          				return $.event.handle.call(this, e);
          			}
          		});
          	};
          	$.extend($.fn, {
          		validateDelegate: function(delegate, type, handler) {
          			return this.bind(type, function(event) {
          				var target = $(event.target);
          				if (target.is(delegate)) {
          					return handler.apply(target, arguments);
          				}
          			});
          		}
          	});
          })(jQuery);
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        18. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (393 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 10254
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10254-1268025194000"
          Last-Modified: Mon, 08 Mar 2010 05:13:14 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10254 bytes)
          /*!
           * jQuery throttle / debounce - v1.1 - 3/7/2010
           * http://benalman.com/projects/jquery-throttle-debounce-plugin/
           * 
           * Copyright (c) 2010 "Cowboy" Ben Alman
           * Dual licensed under the MIT and GPL licenses.
           * http://benalman.com/about/license/
           */
          
          // Script: jQuery throttle / debounce: Sometimes, less is more!
          //
          // *Version: 1.1, Last updated: 3/7/2010*
          // 
          // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
          // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
          // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
          // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
          // 
          // About: License
          // 
          // Copyright (c) 2010 "Cowboy" Ben Alman,
          // Dual licensed under the MIT and GPL licenses.
          // http://benalman.com/about/license/
          // 
          // About: Examples
          // 
          // These working examples, complete with fully commented code, illustrate a few
          // ways in which this plugin can be used.
          // 
          // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
          // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
          // 
          // About: Support and Testing
          // 
          // Information about what version or versions of jQuery this plugin has been
          // tested with, what browsers it has been tested in, and where the unit tests
          // reside (so you can test it yourself).
          // 
          // jQuery Versions - none, 1.3.2, 1.4.2
          // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
          // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
          // 
          // About: Release History
          // 
          // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
          //       executed later than they should. Reworked a fair amount of internal
          //       logic as well.
          // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
          //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
          //       no_trailing throttle parameter and debounce functionality.
          // 
          // Topic: Note for non-jQuery users
          // 
          // jQuery isn't actually required for this plugin, because nothing internal
          // uses any jQuery methods or properties. jQuery is just used as a namespace
          // under which these methods can exist.
          // 
          // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
          // when this plugin is loaded, the method described below will be created in
          // the `Cowboy` namespace. Usage will be exactly the same, but instead of
          // $.method() or jQuery.method(), you'll need to use Cowboy.method().
          
          (function(window,undefined){
            '$:nomunge'; // Used by YUI compressor.
            
            // Since jQuery really isn't required for this plugin, use `jQuery` as the
            // namespace only if it already exists, otherwise use the `Cowboy` namespace,
            // creating it if necessary.
            var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
              
              // Internal method reference.
              jq_throttle;
            
            // Method: jQuery.throttle
            // 
            // Throttle execution of a function. Especially useful for rate limiting
            // execution of handlers on events like resize and scroll. If you want to
            // rate-limit execution of a function to a single time, see the
            // <jQuery.debounce> method.
            // 
            // In this visualization, | is a throttled-function call and X is the actual
            // callback execution:
            // 
            // > Throttled with `no_trailing` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X    X        X    X    X    X    X    X
            // > 
            // > Throttled with `no_trailing` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X             X    X    X    X    X
            // 
            // Usage:
            // 
            // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', throttled );
            // > jQuery('selector').unbind( 'someevent', throttled );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
            //    true, callback will only execute every `delay` milliseconds while the
            //    throttled-function is being called. If no_trailing is false or
            //    unspecified, callback will be executed one final time after the last
            //    throttled-function call. (After the throttled-function has not been
            //    called for `delay` milliseconds, the internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the throttled-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, throttled, function.
            
            $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
              // After wrapper has stopped being called, this timeout ensures that
              // `callback` is executed at the proper times in `throttle` and `end`
              // debounce modes.
              var timeout_id,
                
                // Keep track of the last time `callback` was executed.
                last_exec = 0;
              
              // `no_trailing` defaults to falsy.
              if ( typeof no_trailing !== 'boolean' ) {
                debounce_mode = callback;
                callback = no_trailing;
                no_trailing = undefined;
              }
              
              // The `wrapper` function encapsulates all of the throttling / debouncing
              // functionality and when executed will limit the rate at which `callback`
              // is executed.
              function wrapper() {
                var that = this,
                  elapsed = +new Date() - last_exec,
                  args = arguments;
                
                // Execute `callback` and update the `last_exec` timestamp.
                function exec() {
                  last_exec = +new Date();
                  callback.apply( that, args );
                };
                
                // If `debounce_mode` is true (at_begin) this is used to clear the flag
                // to allow future `callback` executions.
                function clear() {
                  timeout_id = undefined;
                };
                
                if ( debounce_mode && !timeout_id ) {
                  // Since `wrapper` is being called for the first time and
                  // `debounce_mode` is true (at_begin), execute `callback`.
                  exec();
                }
                
                // Clear any existing timeout.
                timeout_id && clearTimeout( timeout_id );
                
                if ( debounce_mode === undefined && elapsed > delay ) {
                  // In throttle mode, if `delay` time has been exceeded, execute
                  // `callback`.
                  exec();
                  
                } else if ( no_trailing !== true ) {
                  // In trailing throttle mode, since `delay` time has not been
                  // exceeded, schedule `callback` to execute `delay` ms after most
                  // recent execution.
                  // 
                  // If `debounce_mode` is true (at_begin), schedule `clear` to execute
                  // after `delay` ms.
                  // 
                  // If `debounce_mode` is false (at end), schedule `callback` to
                  // execute after `delay` ms.
                  timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
                }
              };
              
              // Set the guid of `wrapper` function to the same of original callback, so
              // it can be removed in jQuery 1.4+ .unbind or .die by using the original
              // callback as a reference.
              if ( $.guid ) {
                wrapper.guid = callback.guid = callback.guid || $.guid++;
              }
              
              // Return the wrapper function.
              return wrapper;
            };
            
            // Method: jQuery.debounce
            // 
            // Debounce execution of a function. Debouncing, unlike throttling,
            // guarantees that a function is only executed a single time, either at the
            // very beginning of a series of calls, or at the very end. If you want to
            // simply rate-limit execution of a function, see the <jQuery.throttle>
            // method.
            // 
            // In this visualization, | is a debounced-function call and X is the actual
            // callback execution:
            // 
            // > Debounced with `at_begin` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // >                          X                                 X
            // > 
            // > Debounced with `at_begin` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X                                 X
            // 
            // Usage:
            // 
            // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', debounced );
            // > jQuery('selector').unbind( 'someevent', debounced );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
            //    unspecified, callback will only be executed `delay` milliseconds after
            //    the last debounced-function call. If at_begin is true, callback will be
            //    executed only at the first debounced-function call. (After the
            //    throttled-function has not been called for `delay` milliseconds, the
            //    internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the debounced-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, debounced, function.
            
            $.debounce = function( delay, at_begin, callback ) {
              return callback === undefined
                ? jq_throttle( delay, at_begin, false )
                : jq_throttle( delay, callback, at_begin !== false );
            };
            
          })(this);
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        19. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (398 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 2441
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"2441-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (2441 bytes)
          .dropdown {
          	position: absolute;
          	z-index: 9999999;
          	display: none;
          }
          
          .dropdown .dropdown-menu,
          .dropdown .dropdown-panel {
          	min-width: 160px;
          	max-width: 360px;
          	list-style: none;
          	background: #FFF;
          	border: solid 1px #DDD;
          	border: solid 1px rgba(0, 0, 0, .2);
          	border-radius: 6px;
          	box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
          	overflow: visible;
          	padding: 4px 0;
          	margin: 0;
          }
          
          .dropdown .dropdown-panel {
          	padding: 10px;
          }
          
          .dropdown.dropdown-tip {
          	margin-top: 8px;
          }
          
          .dropdown.dropdown-tip:before {
            position: absolute;
            top: -6px;
            left: 9px;
            content: '';
            border-left: 7px solid transparent;
            border-right: 7px solid transparent;
            border-bottom: 7px solid #CCC;
            border-bottom-color: rgba(0, 0, 0, 0.2);
            display: inline-block;
          }
          
          .dropdown.dropdown-tip.dropdown-anchor-right:before {
          	left: auto;
          	right: 9px;
          }
          
          .dropdown.dropdown-tip:after {
            position: absolute;
            top: -5px;
            left: 10px;
            content: '';
            border-left: 6px solid transparent;
            border-right: 6px solid transparent;
            border-bottom: 6px solid #FFF;
            display: inline-block;
          }
          
          .dropdown.dropdown-tip.dropdown-anchor-right:after {
          	left: auto;
          	right: 10px;
          }
          
          
          .dropdown.dropdown-scroll .dropdown-menu,
          .dropdown.dropdown-scroll .dropdown-panel {
          	max-height: 358px;
          	overflow: auto;
          }
          
          .dropdown .dropdown-menu LI {
          	list-style: none;
          	padding: 0 0;
          	margin: 0;
          	line-height: 18px;
          }
          
          .dropdown .dropdown-menu LI > A,
          .dropdown .dropdown-menu LABEL {
          	display: block;
          	color: #555;
          	text-decoration: none;
          	line-height: 18px;
          	padding: 3px 15px;
          	margin: 0;
          	white-space: nowrap;
          }
          
          .dropdown .dropdown-menu LI > A:hover,
          .dropdown .dropdown-menu LABEL:hover {
          	background-color: #08C;
          	color: #FFF;
          	cursor: pointer;
          }
          
          .dropdown .dropdown-menu .dropdown-divider {
          	font-size: 1px;
          	border-top: solid 1px #E5E5E5;
          	padding: 0;
          	margin: 5px 0;
          }
          
          /* Icon Examples - icons courtesy of http://p.yusukekamiyamane.com/ */
          .dropdown.has-icons LI > A {
          	padding-left: 30px;
          	background-position: 8px center;
          	background-repeat: no-repeat;
          }
          
          .dropdown .undo A { background-image: url(icons/arrow-curve-180-left.png); }
          .dropdown .redo A { background-image: url(icons/arrow-curve.png); }
          .dropdown .cut A { background-image: url(icons/scissors.png); }
          .dropdown .copy A { background-image: url(icons/document-copy.png); }
          .dropdown .paste A { background-image: url(icons/clipboard.png); }
          .dropdown .delete A { background-image: url(icons/cross-script.png); }
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        20. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (401 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 2131
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"2131-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (2131 bytes)
          /*
           * jQuery dropdown: A simple dropdown plugin
           *
           * Copyright A Beautiful Site, LLC. (http://www.abeautifulsite.net/)
           *
           * Licensed under the MIT license: http://opensource.org/licenses/MIT
           *
          */jQuery&&function(e){function t(t,i){var s=t?e(this):i,o=e(s.attr("data-dropdown")),u=s.hasClass("dropdown-open");if(t){if(e(t.target).hasClass("dropdown-ignore"))return;t.preventDefault();t.stopPropagation()}else if(s!==i.target&&e(i.target).hasClass("dropdown-ignore"))return;n();if(u||s.hasClass("dropdown-disabled"))return;s.addClass("dropdown-open");o.data("dropdown-trigger",s).show();r();o.trigger("show",{dropdown:o,trigger:s})}function n(t){var n=t?e(t.target).parents().addBack():null;if(n&&n.is(".dropdown")){if(!n.is(".dropdown-menu"))return;if(!n.is("A"))return}e(document).find(".dropdown:visible").each(function(){var t=e(this);t.hide().removeData("dropdown-trigger").trigger("hide",{dropdown:t})});e(document).find(".dropdown-open").removeClass("dropdown-open")}function r(){var t=e(".dropdown:visible").eq(0),n=t.data("dropdown-trigger"),r=n?parseInt(n.attr("data-horizontal-offset")||0,10):null,i=n?parseInt(n.attr("data-vertical-offset")||0,10):null;if(t.length===0||!n)return;t.hasClass("dropdown-relative")?t.css({left:t.hasClass("dropdown-anchor-right")?n.position().left-(t.outerWidth(!0)-n.outerWidth(!0))-parseInt(n.css("margin-right"),10)+r:n.position().left+parseInt(n.css("margin-left"),10)+r,top:n.position().top+n.outerHeight(!0)-parseInt(n.css("margin-top"),10)+i}):t.css({left:t.hasClass("dropdown-anchor-right")?n.offset().left-(t.outerWidth()-n.outerWidth())+r:n.offset().left+r,top:n.offset().top+n.outerHeight()+i})}e.extend(e.fn,{dropdown:function(r,i){switch(r){case"show":t(null,e(this));return e(this);case"hide":n();return e(this);case"attach":return e(this).attr("data-dropdown",i);case"detach":n();return e(this).removeAttr("data-dropdown");case"disable":return e(this).addClass("dropdown-disabled");case"enable":n();return e(this).removeClass("dropdown-disabled")}}});e(document).on("click.dropdown","[data-dropdown]",t);e(document).on("click.dropdown",n);e(window).on("resize",r)}(jQuery);
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        21. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (419 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 6717
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"6717-1265153602000"
          Last-Modified: Tue, 02 Feb 2010 23:33:22 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (6717 bytes)
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           * 
           * Open source under the BSD License. 
           * 
           * Copyright © 2008 George McGinley Smith
           * All rights reserved.
           * 
           * Redistribution and use in source and binary forms, with or without modification, 
           * are permitted provided that the following conditions are met:
           * 
           * Redistributions of source code must retain the above copyright notice, this list of 
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list 
           * of conditions and the following disclaimer in the documentation and/or other materials 
           * provided with the distribution.
           * 
           * Neither the name of the author nor the names of contributors may be used to endorse 
           * or promote products derived from this software without specific prior written permission.
           * 
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
           * OF THE POSSIBILITY OF SUCH DAMAGE. 
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{}))
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           * 
           * Open source under the BSD License. 
           * 
           * Copyright © 2001 Robert Penner
           * All rights reserved.
           * 
           * Redistribution and use in source and binary forms, with or without modification, 
           * are permitted provided that the following conditions are met:
           * 
           * Redistributions of source code must retain the above copyright notice, this list of 
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list 
           * of conditions and the following disclaimer in the documentation and/or other materials 
           * provided with the distribution.
           * 
           * Neither the name of the author nor the names of contributors may be used to endorse 
           * or promote products derived from this software without specific prior written permission.
           * 
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
           * OF THE POSSIBILITY OF SUCH DAMAGE. 
           *
           */
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        22. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (419 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 8285
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"8285-1267811252000"
          Last-Modified: Fri, 05 Mar 2010 17:47:32 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (8285 bytes)
          /*
           * FancyBox - jQuery Plugin
           * Simple and fancy lightbox alternative
           *
           * Examples and documentation at: http://fancybox.net
           * 
           * Copyright (c) 2008 - 2010 Janis Skarnelis
           *
           * Version: 1.3.1 (05/03/2010)
           * Requires: jQuery v1.3+
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          #fancybox-loading {
          	position: fixed;
          	top: 50%;
          	left: 50%;
          	height: 40px;
          	width: 40px;
          	margin-top: -20px;
          	margin-left: -20px;
          	cursor: pointer;
          	overflow: hidden;
          	z-index: 1104;
          	display: none;
          }
          
          * html #fancybox-loading {	/* IE6 */
          	position: absolute;
          	margin-top: 0;
          }
          
          #fancybox-loading div {
          	position: absolute;
          	top: 0;
          	left: 0;
          	width: 40px;
          	height: 480px;
          	background-image: url('fancybox.png');
          }
          
          #fancybox-overlay {
          	position: fixed;
          	top: 0;
          	left: 0;
          	bottom: 0;
          	right: 0;
          	background: #000;
          	z-index: 1100;
          	display: none;
          }
          
          * html #fancybox-overlay {	/* IE6 */
          	position: absolute;
          	width: 100%;
          }
          
          #fancybox-tmp {
          	padding: 0;
          	margin: 0;
          	border: 0;
          	overflow: auto;
          	display: none;
          }
          
          #fancybox-wrap {
          	position: absolute;
          	top: 0;
          	left: 0;
          	margin: 0;
          	padding: 20px;
          	z-index: 1101;
          	display: none;
          }
          
          #fancybox-outer {
          	position: relative;
          	width: 100%;
          	height: 100%;
          	background: #FFF;
          }
          
          #fancybox-inner {
          	position: absolute;
          	top: 0;
          	left: 0;
          	width: 1px;
          	height: 1px;
          	padding: 0;
          	margin: 0;
          	outline: none;
          	overflow: hidden;
          }
          
          #fancybox-hide-sel-frame {
          	position: absolute;
          	top: 0;
          	left: 0;
          	width: 100%;
          	height: 100%;
          	background: transparent;
          }
          
          #fancybox-close {
          	position: absolute;
          	top: -15px;
          	right: -15px;
          	width: 30px;
          	height: 30px;
          	background-image: url('fancybox.png');
          	background-position: -40px 0px;
          	cursor: pointer;
          	z-index: 1103;
          	display: none;
          }
          
          #fancybox_error {
          	color: #444;
          	font: normal 12px/20px Arial;
          	padding: 7px;
          	margin: 0;
          }
          
          #fancybox-content {
          	height: auto;
          	width: auto;
          	padding: 0;
          	margin: 0;
          }
          
          #fancybox-img {
          	width: 100%;
          	height: 100%;
          	padding: 0;
          	margin: 0;
          	border: none;
          	outline: none;
          	line-height: 0;
          	vertical-align: top;
          	-ms-interpolation-mode: bicubic;
          }
          
          #fancybox-frame {
          	position: relative;
          	width: 100%;
          	height: 100%;
          	border: none;
          	display: block;
          }
          
          #fancybox-title {
          	position: absolute;
          	bottom: 0;
          	left: 0;
          	font-family: Arial;
          	font-size: 12px;
          	z-index: 1102;
          }
          
          .fancybox-title-inside {
          	padding: 10px 0;
          	text-align: center;
          	color: #333;
          }
          
          .fancybox-title-outside {
          	padding-top: 5px;
          	color: #FFF;
          	text-align: center;
          	font-weight: bold;
          }
          
          .fancybox-title-over {
          	color: #FFF;
          	text-align: left;
          }
          
          #fancybox-title-over {
          	padding: 10px;
          	background-image: url('fancy_title_over.png');
          	display: block;
          }
          
          #fancybox-title-wrap {
          	display: inline-block;
          }
          
          #fancybox-title-wrap span {
          	height: 32px;
          	float: left;
          }
          
          #fancybox-title-left {
          	padding-left: 15px;
          	background-image: url('fancybox.png');
          	background-position: -40px -90px;
          	background-repeat: no-repeat;
          }
          
          #fancybox-title-main {
          	font-weight: bold;
          	line-height: 29px;
          	background-image: url('fancybox-x.png');
          	background-position: 0px -40px;
          	color: #FFF;
          }
          
          #fancybox-title-right {
          	padding-left: 15px;
          	background-image: url('fancybox.png');
          	background-position: -55px -90px;
          	background-repeat: no-repeat;
          }
          
          #fancybox-left, #fancybox-right {
          	position: absolute;
          	bottom: 0px;
          	height: 100%;
          	width: 35%;
          	cursor: pointer;
          	outline: none;
          	background-image: url('blank.gif');
          	z-index: 1102;
          	display: none;
          }
          
          #fancybox-left {
          	left: 0px;
          }
          
          #fancybox-right {
          	right: 0px;
          }
          
          #fancybox-left-ico, #fancybox-right-ico {
          	position: absolute;
          	top: 50%;
          	left: -9999px;
          	width: 30px;
          	height: 30px;
          	margin-top: -15px;
          	cursor: pointer;
          	z-index: 1102;
          	display: block;
          }
          
          #fancybox-left-ico {
          	background-image: url('fancybox.png');
          	background-position: -40px -30px;
          }
          
          #fancybox-right-ico {
          	background-image: url('fancybox.png');
          	background-position: -40px -60px;
          }
          
          #fancybox-left:hover, #fancybox-right:hover {
          	visibility: visible;    /* IE6 */
          }
          
          #fancybox-left:hover span {
          	left: 20px;
          }
          
          #fancybox-right:hover span {
          	left: auto;
          	right: 20px;
          }
          
          .fancy-bg {
          	position: absolute;
          	padding: 0;
          	margin: 0;
          	border: 0;
          	width: 20px;
          	height: 20px;
          	z-index: 1001;
          }
          
          #fancy-bg-n {
          	top: -20px;
          	left: 0;
          	width: 100%;
          	background-image: url('fancybox-x.png');
          }
          
          #fancy-bg-ne {
          	top: -20px;
          	right: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -162px;
          }
          
          #fancy-bg-e {
          	top: 0;
          	right: -20px;
          	height: 100%;
          	background-image: url('fancybox-y.png');
          	background-position: -20px 0px;
          }
          
          #fancy-bg-se {
          	bottom: -20px;
          	right: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -182px; 
          }
          
          #fancy-bg-s {
          	bottom: -20px;
          	left: 0;
          	width: 100%;
          	background-image: url('fancybox-x.png');
          	background-position: 0px -20px;
          }
          
          #fancy-bg-sw {
          	bottom: -20px;
          	left: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -142px;
          }
          
          #fancy-bg-w {
          	top: 0;
          	left: -20px;
          	height: 100%;
          	background-image: url('fancybox-y.png');
          }
          
          #fancy-bg-nw {
          	top: -20px;
          	left: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -122px;
          }
          
          /* IE */
          
          #fancybox-loading.fancybox-ie div	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-close		{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); }
          
          .fancybox-ie #fancybox-title-over	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
          .fancybox-ie #fancybox-title-left	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-title-main	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-title-right	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); }
          
          .fancybox-ie #fancybox-left-ico		{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-right-ico	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); }
          
          .fancybox-ie .fancy-bg { background: transparent !important; }
          
          .fancybox-ie #fancy-bg-n	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-ne	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-e	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-se	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-s	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-sw	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-w	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-nw	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        23. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (418 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 28094
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"28094-1267813320000"
          Last-Modified: Fri, 05 Mar 2010 18:22:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (28094 bytes)
          /*
           * FancyBox - jQuery Plugin
           * Simple and fancy lightbox alternative
           *
           * Examples and documentation at: http://fancybox.net
           * 
           * Copyright (c) 2008 - 2010 Janis Skarnelis
           *
           * Version: 1.3.1 (05/03/2010)
           * Requires: jQuery v1.3+
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          	var tmp, loading, overlay, wrap, outer, inner, close, nav_left, nav_right,
          
          		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
          
          		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
          
          		loadingTimer, loadingFrame = 1,
          
          		start_pos, final_pos, busy = false, shadow = 20, fx = $.extend($('<div/>')[0], { prop: 0 }), titleh = 0, 
          
          		isIE6 = !$.support.opacity && !window.XMLHttpRequest,
          
          		/*
          		 * Private methods 
          		 */
          
          		fancybox_abort = function() {
          			loading.hide();
          
          			imgPreloader.onerror = imgPreloader.onload = null;
          
          			if (ajaxLoader) {
          				ajaxLoader.abort();
          			}
          
          			tmp.empty();
          		},
          
          		fancybox_error = function() {
          			$.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', {
          				'scrolling'		: 'no',
          				'padding'		: 20,
          				'transitionIn'	: 'none',
          				'transitionOut'	: 'none'
          			});
          		},
          
          		fancybox_get_viewport = function() {
          			return [ $(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ];
          		},
          
          		fancybox_get_zoom_to = function () {
          			var view	= fancybox_get_viewport(),
          				to		= {},
          
          				margin = currentOpts.margin,
          				resize = currentOpts.autoScale,
          
          				horizontal_space	= (shadow + margin) * 2,
          				vertical_space		= (shadow + margin) * 2,
          				double_padding		= (currentOpts.padding * 2),
          				
          				ratio;
          
          			if (currentOpts.width.toString().indexOf('%') > -1) {
          				to.width = ((view[0] * parseFloat(currentOpts.width)) / 100) - (shadow * 2) ;
          				resize = false;
          
          			} else {
          				to.width = currentOpts.width + double_padding;
          			}
          
          			if (currentOpts.height.toString().indexOf('%') > -1) {
          				to.height = ((view[1] * parseFloat(currentOpts.height)) / 100) - (shadow * 2);
          				resize = false;
          
          			} else {
          				to.height = currentOpts.height + double_padding;
          			}
          
          			if (resize && (to.width > (view[0] - horizontal_space) || to.height > (view[1] - vertical_space))) {
          				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
          					horizontal_space	+= double_padding;
          					vertical_space		+= double_padding;
          
          					ratio = Math.min(Math.min( view[0] - horizontal_space, currentOpts.width) / currentOpts.width, Math.min( view[1] - vertical_space, currentOpts.height) / currentOpts.height);
          
          					to.width	= Math.round(ratio * (to.width	- double_padding)) + double_padding;
          					to.height	= Math.round(ratio * (to.height	- double_padding)) + double_padding;
          
          				} else {
          					to.width	= Math.min(to.width,	(view[0] - horizontal_space));
          					to.height	= Math.min(to.height,	(view[1] - vertical_space));
          				}
          			}
          
          			to.top	= view[3] + ((view[1] - (to.height	+ (shadow * 2 ))) * 0.5);
          			to.left	= view[2] + ((view[0] - (to.width	+ (shadow * 2 ))) * 0.5);
          
          			if (currentOpts.autoScale === false) {
          				to.top	= Math.max(view[3] + margin, to.top);
          				to.left	= Math.max(view[2] + margin, to.left);
          			}
          
          			return to;
          		},
          
          		fancybox_format_title = function(title) {
          			if (title && title.length) {
          				switch (currentOpts.titlePosition) {
          					case 'inside':
          						return title;
          					case 'over':
          						return '<span id="fancybox-title-over">' + title + '</span>';
          					default:
          						return '<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">' + title + '</span><span id="fancybox-title-right"></span></span>';
          				}
          			}
          
          			return false;
          		},
          
          		fancybox_process_title = function() {
          			var title	= currentOpts.title,
          				width	= final_pos.width - (currentOpts.padding * 2),
          				titlec	= 'fancybox-title-' + currentOpts.titlePosition;
          				
          			$('#fancybox-title').remove();
          
          			titleh = 0;
          
          			if (currentOpts.titleShow === false) {
          				return;
          			}
          
          			title = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(title, currentArray, currentIndex, currentOpts) : fancybox_format_title(title);
          
          			if (!title || title === '') {
          				return;
          			}
          
          			$('<div id="fancybox-title" class="' + titlec + '" />').css({
          				'width'			: width,
          				'paddingLeft'	: currentOpts.padding,
          				'paddingRight'	: currentOpts.padding
          			}).html(title).appendTo('body');
          
          			switch (currentOpts.titlePosition) {
          				case 'inside':
          					titleh = $("#fancybox-title").outerHeight(true) - currentOpts.padding;
          					final_pos.height += titleh;
          				break;
          
          				case 'over':
          					$('#fancybox-title').css('bottom', currentOpts.padding);
          				break;
          
          				default:
          					$('#fancybox-title').css('bottom', $("#fancybox-title").outerHeight(true) * -1);
          				break;
          			}
          
          			$('#fancybox-title').appendTo( outer ).hide();
          		},
          
          		fancybox_set_navigation = function() {
          			$(document).unbind('keydown.fb').bind('keydown.fb', function(e) {
          				if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
          					e.preventDefault();
          					$.fancybox.close();
          
          				} else if (e.keyCode == 37) {
          					e.preventDefault();
          					$.fancybox.prev();
          
          				} else if (e.keyCode == 39) {
          					e.preventDefault();
          					$.fancybox.next();
          				}
          			});
          
          			if ($.fn.mousewheel) {
          				wrap.unbind('mousewheel.fb');
          
          				if (currentArray.length > 1) {
          					wrap.bind('mousewheel.fb', function(e, delta) {
          						e.preventDefault();
          
          						if (busy || delta === 0) {
          							return;
          						}
          
          						if (delta > 0) {
          							$.fancybox.prev();
          						} else {
          							$.fancybox.next();
          						}
          					});
          				}
          			}
          
          			if (!currentOpts.showNavArrows) { return; }
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
          				nav_left.show();
          			}
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
          				nav_right.show();
          			}
          		},
          
          		fancybox_preload_images = function() {
          			var href, 
          				objNext;
          				
          			if ((currentArray.length -1) > currentIndex) {
          				href = currentArray[ currentIndex + 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          
          			if (currentIndex > 0) {
          				href = currentArray[ currentIndex - 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          		},
          
          		_finish = function () {
          			inner.css('overflow', (currentOpts.scrolling == 'auto' ? (currentOpts.type == 'image' || currentOpts.type == 'iframe' || currentOpts.type == 'swf' ? 'hidden' : 'auto') : (currentOpts.scrolling == 'yes' ? 'auto' : 'visible')));
          
          			if (!$.support.opacity) {
          				inner.get(0).style.removeAttribute('filter');
          				wrap.get(0).style.removeAttribute('filter');
          			}
          
          			$('#fancybox-title').show();
          
          			if (currentOpts.hideOnContentClick)	{
          				inner.one('click', $.fancybox.close);
          			}
          			if (currentOpts.hideOnOverlayClick)	{
          				overlay.one('click', $.fancybox.close);
          			}
          
          			if (currentOpts.showCloseButton) {
          				close.show();
          			}
          
          			fancybox_set_navigation();
          
          			$(window).bind("resize.fb", $.fancybox.center);
          
          			if (currentOpts.centerOnScroll) {
          				$(window).bind("scroll.fb", $.fancybox.center);
          			} else {
          				$(window).unbind("scroll.fb");
          			}
          
          			if ($.isFunction(currentOpts.onComplete)) {
          				currentOpts.onComplete(currentArray, currentIndex, currentOpts);
          			}
          
          			busy = false;
          
          			fancybox_preload_images();
          		},
          
          		fancybox_draw = function(pos) {
          			var width	= Math.round(start_pos.width	+ (final_pos.width	- start_pos.width)	* pos),
          				height	= Math.round(start_pos.height	+ (final_pos.height	- start_pos.height)	* pos),
          
          				top		= Math.round(start_pos.top	+ (final_pos.top	- start_pos.top)	* pos),
          				left	= Math.round(start_pos.left	+ (final_pos.left	- start_pos.left)	* pos);
          
          			wrap.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px',
          				'top'		: top		+ 'px',
          				'left'		: left		+ 'px'
          			});
          
          			width	= Math.max(width - currentOpts.padding * 2, 0);
          			height	= Math.max(height - (currentOpts.padding * 2 + (titleh * pos)), 0);
          
          			inner.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px'
          			});
          
          			if (typeof final_pos.opacity !== 'undefined') {
          				wrap.css('opacity', (pos < 0.5 ? 0.5 : pos));
          			}
          		},
          
          		fancybox_get_obj_pos = function(obj) {
          			var pos		= obj.offset();
          
          			pos.top		+= parseFloat( obj.css('paddingTop') )	|| 0;
          			pos.left	+= parseFloat( obj.css('paddingLeft') )	|| 0;
          
          			pos.top		+= parseFloat( obj.css('border-top-width') )	|| 0;
          			pos.left	+= parseFloat( obj.css('border-left-width') )	|| 0;
          
          			pos.width	= obj.width();
          			pos.height	= obj.height();
          
          			return pos;
          		},
          
          		fancybox_get_zoom_from = function() {
          			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
          				from = {},
          				pos,
          				view;
          
          			if (orig && orig.length) {
          				pos = fancybox_get_obj_pos(orig);
          
          				from = {
          					width	: (pos.width	+ (currentOpts.padding * 2)),
          					height	: (pos.height	+ (currentOpts.padding * 2)),
          					top		: (pos.top		- currentOpts.padding - shadow),
          					left	: (pos.left		- currentOpts.padding - shadow)
          				};
          				
          			} else {
          				view = fancybox_get_viewport();
          
          				from = {
          					width	: 1,
          					height	: 1,
          					top		: view[3] + view[1] * 0.5,
          					left	: view[2] + view[0] * 0.5
          				};
          			}
          
          			return from;
          		},
          
          		fancybox_show = function() {
          			loading.hide();
          
          			if (wrap.is(":visible") && $.isFunction(currentOpts.onCleanup)) {
          				if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          					$.event.trigger('fancybox-cancel');
          
          					busy = false;
          					return;
          				}
          			}
          
          			currentArray	= selectedArray;
          			currentIndex	= selectedIndex;
          			currentOpts		= selectedOpts;
          
          			inner.get(0).scrollTop	= 0;
          			inner.get(0).scrollLeft	= 0;
          
          			if (currentOpts.overlayShow) {
          				if (isIE6) {
          					$('select:not(#fancybox-tmp select)').filter(function() {
          						return this.style.visibility !== 'hidden';
          					}).css({'visibility':'hidden'}).one('fancybox-cleanup', function() {
          						this.style.visibility = 'inherit';
          					});
          				}
          
          				overlay.css({
          					'background-color'	: currentOpts.overlayColor,
          					'opacity'			: currentOpts.overlayOpacity
          				}).unbind().show();
          			}
          
          			final_pos = fancybox_get_zoom_to();
          
          			fancybox_process_title();
          
          			if (wrap.is(":visible")) {
          				$( close.add( nav_left ).add( nav_right ) ).hide();
          
          				var pos = wrap.position(),
          					equal;
          
          				start_pos = {
          					top		:	pos.top ,
          					left	:	pos.left,
          					width	:	wrap.width(),
          					height	:	wrap.height()
          				};
          
          				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
          
          				inner.fadeOut(currentOpts.changeFade, function() {
          					var finish_resizing = function() {
          						inner.html( tmp.contents() ).fadeIn(currentOpts.changeFade, _finish);
          					};
          					
          					$.event.trigger('fancybox-change');
          
          					inner.empty().css('overflow', 'hidden');
          
          					if (equal) {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          						});
          						
          						finish_resizing();
          
          					} else {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          						});
          						
          						fx.prop = 0;
          
          						$(fx).animate({ prop: 1 }, {
          							 duration	: currentOpts.changeSpeed,
          							 easing		: currentOpts.easingChange,
          							 step		: fancybox_draw,
          							 complete	: finish_resizing
          						});
          					}
          				});
          
          				return;
          			}
          
          			wrap.css('opacity', 1);
          
          			if (currentOpts.transitionIn == 'elastic') {
          				start_pos = fancybox_get_zoom_from();
          
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css(start_pos).show();
          
          				if (currentOpts.opacity) {
          					final_pos.opacity = 0;
          				}
          
          				fx.prop = 0;
          
          				$(fx).animate({ prop: 1 }, {
          					 duration	: currentOpts.speedIn,
          					 easing		: currentOpts.easingIn,
          					 step		: fancybox_draw,
          					 complete	: _finish
          				});
          
          			} else {
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css( final_pos ).fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
          			}
          		},
          
          		fancybox_process_inline = function() {
          			tmp.width(	selectedOpts.width );
          			tmp.height(	selectedOpts.height );
          
          			if (selectedOpts.width	== 'auto') {
          				selectedOpts.width = tmp.width();
          			}
          			if (selectedOpts.height	== 'auto') {
          				selectedOpts.height	= tmp.height();
          			}
          
          			fancybox_show();
          		},
          		
          		fancybox_process_image = function() {
          			busy = true;
          
          			selectedOpts.width	= imgPreloader.width;
          			selectedOpts.height	= imgPreloader.height;
          
          			$("<img />").attr({
          				'id'	: 'fancybox-img',
          				'src'	: imgPreloader.src,
          				'alt'	: selectedOpts.title
          			}).appendTo( tmp );
          
          			fancybox_show();
          		},
          
          		fancybox_start = function() {
          			fancybox_abort();
          
          			var obj	= selectedArray[ selectedIndex ],
          				href, 
          				type, 
          				title,
          				str,
          				emb,
          				selector,
          				data;
          
          			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
          			title = obj.title || $(obj).title || selectedOpts.title || '';
          			
          			if (obj.nodeName && !selectedOpts.orig) {
          				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
          			}
          
          			if (title === '' && selectedOpts.orig) {
          				title = selectedOpts.orig.attr('alt');
          			}
          
          			if (obj.nodeName && (/^(?:javascript|#)/i).test(obj.href)) {
          				href = selectedOpts.href || null;
          			} else {
          				href = selectedOpts.href || obj.href || null;
          			}
          
          			if (selectedOpts.type) {
          				type = selectedOpts.type;
          
          				if (!href) {
          					href = selectedOpts.content;
          				}
          				
          			} else if (selectedOpts.content) {
          				type	= 'html';
          
          			} else if (href) {
          				if (href.match(imgRegExp)) {
          					type = 'image';
          
          				} else if (href.match(swfRegExp)) {
          					type = 'swf';
          
          				} else if ($(obj).hasClass("iframe")) {
          					type = 'iframe';
          
          				} else if (href.match(/#/)) {
          					obj = href.substr(href.indexOf("#"));
          
          					type = $(obj).length > 0 ? 'inline' : 'ajax';
          				} else {
          					type = 'ajax';
          				}
          			} else {
          				type = 'inline';
          			}
          
          			selectedOpts.type	= type;
          			selectedOpts.href	= href;
          			selectedOpts.title	= title;
          
          			if (selectedOpts.autoDimensions && selectedOpts.type !== 'iframe' && selectedOpts.type !== 'swf') {
          				selectedOpts.width		= 'auto';
          				selectedOpts.height		= 'auto';
          			}
          
          			if (selectedOpts.modal) {
          				selectedOpts.overlayShow		= true;
          				selectedOpts.hideOnOverlayClick	= false;
          				selectedOpts.hideOnContentClick	= false;
          				selectedOpts.enableEscapeButton	= false;
          				selectedOpts.showCloseButton	= false;
          			}
          
          			if ($.isFunction(selectedOpts.onStart)) {
          				if (selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts) === false) {
          					busy = false;
          					return;
          				}
          			}
          
          			tmp.css('padding', (shadow + selectedOpts.padding + selectedOpts.margin));
          
          			$('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
          				$(this).replaceWith(inner.children());
          			});
          
          			switch (type) {
          				case 'html' :
          					tmp.html( selectedOpts.content );
          					fancybox_process_inline();
          				break;
          
          				case 'inline' :
          					$('<div class="fancybox-inline-tmp" />').hide().insertBefore( $(obj) ).bind('fancybox-cleanup', function() {
          						$(this).replaceWith(inner.children());
          					}).bind('fancybox-cancel', function() {
          						$(this).replaceWith(tmp.children());
          					});
          
          					$(obj).appendTo(tmp);
          
          					fancybox_process_inline();
          				break;
          
          				case 'image':
          					busy = false;
          
          					$.fancybox.showActivity();
          
          					imgPreloader = new Image();
          
          					imgPreloader.onerror = function() {
          						fancybox_error();
          					};
          
          					imgPreloader.onload = function() {
          						imgPreloader.onerror = null;
          						imgPreloader.onload = null;
          						fancybox_process_image();
          					};
          
          					imgPreloader.src = href;
          		
          				break;
          
          				case 'swf':
          					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
          					emb = '';
          					
          					$.each(selectedOpts.swf, function(name, val) {
          						str += '<param name="' + name + '" value="' + val + '"></param>';
          						emb += ' ' + name + '="' + val + '"';
          					});
          
          					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
          
          					tmp.html(str);
          
          					fancybox_process_inline();
          				break;
          
          				case 'ajax':
          					selector	= href.split('#', 2);
          					data		= selectedOpts.ajax.data || {};
          
          					if (selector.length > 1) {
          						href = selector[0];
          
          						if (typeof data == "string") {
          							data += '&selector=' + selector[1];
          						} else {
          							data.selector = selector[1];
          						}
          					}
          
          					busy = false;
          					$.fancybox.showActivity();
          
          					ajaxLoader = $.ajax($.extend(selectedOpts.ajax, {
          						url		: href,
          						data	: data,
          						error	: fancybox_error,
          						success : function(data, textStatus, XMLHttpRequest) {
          							if (ajaxLoader.status == 200) {
          								tmp.html( data );
          								fancybox_process_inline();
          							}
          						}
          					}));
          
          				break;
          
          				case 'iframe' :
          					$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" scrolling="' + selectedOpts.scrolling + '" src="' + selectedOpts.href + '"></iframe>').appendTo(tmp);
          					fancybox_show();
          				break;
          			}
          		},
          
          		fancybox_animate_loading = function() {
          			if (!loading.is(':visible')){
          				clearInterval(loadingTimer);
          				return;
          			}
          
          			$('div', loading).css('top', (loadingFrame * -40) + 'px');
          
          			loadingFrame = (loadingFrame + 1) % 12;
          		},
          
          		fancybox_init = function() {
          			if ($("#fancybox-wrap").length) {
          				return;
          			}
          
          			$('body').append(
          				tmp			= $('<div id="fancybox-tmp"></div>'),
          				loading		= $('<div id="fancybox-loading"><div></div></div>'),
          				overlay		= $('<div id="fancybox-overlay"></div>'),
          				wrap		= $('<div id="fancybox-wrap"></div>')
          			);
          
          			if (!$.support.opacity) {
          				wrap.addClass('fancybox-ie');
          				loading.addClass('fancybox-ie');
          			}
          
          			outer = $('<div id="fancybox-outer"></div>')
          				.append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>')
          				.appendTo( wrap );
          
          			outer.append(
          				inner		= $('<div id="fancybox-inner"></div>'),
          				close		= $('<a id="fancybox-close"></a>'),
          
          				nav_left	= $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
          				nav_right	= $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
          			);
          
          			close.click($.fancybox.close);
          			loading.click($.fancybox.cancel);
          
          			nav_left.click(function(e) {
          				e.preventDefault();
          				$.fancybox.prev();
          			});
          
          			nav_right.click(function(e) {
          				e.preventDefault();
          				$.fancybox.next();
          			});
          
          			if (isIE6) {
          				overlay.get(0).style.setExpression('height',	"document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");
          				loading.get(0).style.setExpression('top',		"(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");
          
          				outer.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>');
          			}
          		};
          
          	/*
          	 * Public methods 
          	 */
          
          	$.fn.fancybox = function(options) {
          		$(this)
          			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
          			.unbind('click.fb').bind('click.fb', function(e) {
          				e.preventDefault();
          
          				if (busy) {
          					return;
          				}
          
          				busy = true;
          
          				$(this).blur();
          
          				selectedArray	= [];
          				selectedIndex	= 0;
          
          				var rel = $(this).attr('rel') || '';
          
          				if (!rel || rel == '' || rel === 'nofollow') {
          					selectedArray.push(this);
          
          				} else {
          					selectedArray	= $("a[rel=" + rel + "], area[rel=" + rel + "]");
          					selectedIndex	= selectedArray.index( this );
          				}
          
          				fancybox_start();
          
          				return false;
          			});
          
          		return this;
          	};
          
          	$.fancybox = function(obj) {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		var opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
          
          		selectedArray	= [];
          		selectedIndex	= opts.index || 0;
          
          		if ($.isArray(obj)) {
          			for (var i = 0, j = obj.length; i < j; i++) {
          				if (typeof obj[i] == 'object') {
          					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
          				} else {
          					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
          				}
          			}
          
          			selectedArray = jQuery.merge(selectedArray, obj);
          
          		} else {
          			if (typeof obj == 'object') {
          				$(obj).data('fancybox', $.extend({}, opts, obj));
          			} else {
          				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
          			}
          
          			selectedArray.push(obj);
          		}
          
          		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
          			selectedIndex = 0;
          		}
          
          		fancybox_start();
          	};
          
          	$.fancybox.showActivity = function() {
          		clearInterval(loadingTimer);
          
          		loading.show();
          		loadingTimer = setInterval(fancybox_animate_loading, 66);
          	};
          
          	$.fancybox.hideActivity = function() {
          		loading.hide();
          	};
          
          	$.fancybox.next = function() {
          		return $.fancybox.pos( currentIndex + 1);
          	};
          	
          	$.fancybox.prev = function() {
          		return $.fancybox.pos( currentIndex - 1);
          	};
          
          	$.fancybox.pos = function(pos) {
          		if (busy) {
          			return;
          		}
          
          		pos = parseInt(pos, 10);
          
          		if (pos > -1 && currentArray.length > pos) {
          			selectedIndex = pos;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos < 0) {
          			selectedIndex = currentArray.length - 1;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos >= currentArray.length) {
          			selectedIndex = 0;
          			fancybox_start();
          		}
          
          		return;
          	};
          
          	$.fancybox.cancel = function() {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		$.event.trigger('fancybox-cancel');
          
          		fancybox_abort();
          
          		if (selectedOpts && $.isFunction(selectedOpts.onCancel)) {
          			selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
          		}
          
          		busy = false;
          	};
          
          	// Note: within an iframe use - parent.$.fancybox.close();
          	$.fancybox.close = function() {
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		if (currentOpts && $.isFunction(currentOpts.onCleanup)) {
          			if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          				busy = false;
          				return;
          			}
          		}
          
          		fancybox_abort();
          
          		$(close.add( nav_left ).add( nav_right )).hide();
          
          		$('#fancybox-title').remove();
          
          		wrap.add(inner).add(overlay).unbind();
          
          		$(window).unbind("resize.fb scroll.fb");
          		$(document).unbind('keydown.fb');
          
          		function _cleanup() {
          			overlay.fadeOut('fast');
          
          			wrap.hide();
          
          			$.event.trigger('fancybox-cleanup');
          
          			inner.empty();
          
          			if ($.isFunction(currentOpts.onClosed)) {
          				currentOpts.onClosed(currentArray, currentIndex, currentOpts);
          			}
          
          			currentArray	= selectedOpts	= [];
          			currentIndex	= selectedIndex	= 0;
          			currentOpts		= selectedOpts	= {};
          
          			busy = false;
          		}
          
          		inner.css('overflow', 'hidden');
          
          		if (currentOpts.transitionOut == 'elastic') {
          			start_pos = fancybox_get_zoom_from();
          
          			var pos = wrap.position();
          
          			final_pos = {
          				top		:	pos.top ,
          				left	:	pos.left,
          				width	:	wrap.width(),
          				height	:	wrap.height()
          			};
          
          			if (currentOpts.opacity) {
          				final_pos.opacity = 1;
          			}
          
          			fx.prop = 1;
          
          			$(fx).animate({ prop: 0 }, {
          				 duration	: currentOpts.speedOut,
          				 easing		: currentOpts.easingOut,
          				 step		: fancybox_draw,
          				 complete	: _cleanup
          			});
          
          		} else {
          			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
          		}
          	};
          
          	$.fancybox.resize = function() {
          		var c, h;
          		
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		c = inner.wrapInner("<div style='overflow:auto'></div>").children();
          		h = c.height();
          
          		wrap.css({height:	h + (currentOpts.padding * 2) + titleh});
          		inner.css({height:	h});
          
          		c.replaceWith(c.children());
          
          		$.fancybox.center();
          	};
          
          	$.fancybox.center = function() {
          		busy = true;
          
          		var view	= fancybox_get_viewport(),
          			margin	= currentOpts.margin,
          			to		= {};
          
          		to.top	= view[3] + ((view[1] - ((wrap.height() - titleh) + (shadow * 2 ))) * 0.5);
          		to.left	= view[2] + ((view[0] - (wrap.width() + (shadow * 2 ))) * 0.5);
          
          		to.top	= Math.max(view[3] + margin, to.top);
          		to.left	= Math.max(view[2] + margin, to.left);
          
          		wrap.css(to);
          
          		busy = false;
          	};
          
          	$.fn.fancybox.defaults = {
          		padding				:	10,
          		margin				:	20,
          		opacity				:	false,
          		modal				:	false,
          		cyclic				:	false,
          		scrolling			:	'auto',	// 'auto', 'yes' or 'no'
          
          		width				:	560,
          		height				:	340,
          
          		autoScale			:	true,
          		autoDimensions		:	true,
          		centerOnScroll		:	false,
          
          		ajax				:	{},
          		swf					:	{ wmode: 'transparent' },
          
          		hideOnOverlayClick	:	true,
          		hideOnContentClick	:	false,
          
          		overlayShow			:	true,
          		overlayOpacity		:	0.3,
          		overlayColor		:	'#666',
          
          		titleShow			:	true,
          		titlePosition		:	'outside',	// 'outside', 'inside' or 'over'
          		titleFormat			:	null,
          
          		transitionIn		:	'fade',	// 'elastic', 'fade' or 'none'
          		transitionOut		:	'fade',	// 'elastic', 'fade' or 'none'
          
          		speedIn				:	300,
          		speedOut			:	300,
          
          		changeSpeed			:	300,
          		changeFade			:	'fast',
          
          		easingIn			:	'swing',
          		easingOut			:	'swing',
          
          		showCloseButton		:	true,
          		showNavArrows		:	true,
          		enableEscapeButton	:	true,
          
          		onStart				:	null,
          		onCancel			:	null,
          		onComplete			:	null,
          		onCleanup			:	null,
          		onClosed			:	null
          	};
          
          	$(document).ready(function() {
          		fancybox_init();
          	});
          
          })(jQuery);
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        24. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.form.min.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (381 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.form.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 14504
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"14504-1371572158000"
          Last-Modified: Tue, 18 Jun 2013 16:15:58 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (14504 bytes)
          /*
          * jQuery Form Plugin; v20130616
          * http://jquery.malsup.com/form/
          * Copyright (c) 2013 M. Alsup; Dual licensed: MIT/GPL
          * https://github.com/malsup/form#copyright-and-license
          */
          ;(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(this).ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=this;if(i.clk=r,"image"==r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n={};n.fileapi=void 0!==e("<input type='file'/>").get(0).files,n.formdata=void 0!==window.FormData;var i=!!e.fn.prop;e.fn.attr2=function(){if(!i)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t){function r(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;o>a;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function o(a){for(var n=new FormData,i=0;a.length>i;i++)n.append(a[i].name,a[i].value);if(t.extraData){var o=r(t.extraData);for(i=0;o.length>i;i++)o[i]&&n.append(o[i][0],o[i][1])}t.data=null;var s=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:u||"POST"});t.uploadProgress&&(s.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(100*(a/n))),t.uploadProgress(e,a,n,r)},!1),r}),s.data=null;var l=s.beforeSend;return s.beforeSend=function(e,t){t.data=n,l&&l.call(this,e,t)},e.ajax(s)}function s(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(r){a("cannot get iframe.contentWindow document: "+r)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function o(){function t(){try{var e=n(g).readyState;a("state = "+e),e&&"uninitialized"==e.toLowerCase()&&setTimeout(t,50)}catch(r){a("Server abort: ",r," (",r.name,")"),s(D),j&&clearTimeout(j),j=void 0}}var r=f.attr2("target"),i=f.attr2("action");w.setAttribute("target",d),u||w.setAttribute("method","POST"),i!=m.url&&w.setAttribute("action",m.url),m.skipEncodingOverride||u&&!/post/i.test(u)||f.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),m.timeout&&(j=setTimeout(function(){T=!0,s(k)},m.timeout));var o=[];try{if(m.extraData)for(var l in m.extraData)m.extraData.hasOwnProperty(l)&&(e.isPlainObject(m.extraData[l])&&m.extraData[l].hasOwnProperty("name")&&m.extraData[l].hasOwnProperty("value")?o.push(e('<input type="hidden" name="'+m.extraData[l].name+'">').val(m.extraData[l].value).appendTo(w)[0]):o.push(e('<input type="hidden" name="'+l+'">').val(m.extraData[l]).appendTo(w)[0]));m.iframeTarget||(v.appendTo("body"),g.attachEvent?g.attachEvent("onload",s):g.addEventListener("load",s,!1)),setTimeout(t,15);try{w.submit()}catch(c){var p=document.createElement("form").submit;p.apply(w)}}finally{w.setAttribute("action",i),r?w.setAttribute("target",r):f.removeAttr("target"),e(o).remove()}}function s(t){if(!x.aborted&&!F){if(M=n(g),M||(a("cannot access response document"),t=D),t===k&&x)return x.abort("timeout"),S.reject(x,"timeout"),void 0;if(t==D&&x)return x.abort("server abort"),S.reject(x,"error","server abort"),void 0;if(M&&M.location.href!=m.iframeSrc||T){g.detachEvent?g.detachEvent("onload",s):g.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"==m.dataType||M.XMLDocument||e.isXMLDoc(M);if(a("isXml="+o),!o&&window.opera&&(null===M.body||!M.body.innerHTML)&&--O)return a("requeing onLoad callback, DOM not available"),setTimeout(s,250),void 0;var u=M.body?M.body:M.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=M.XMLDocument?M.XMLDocument:M,o&&(m.dataType="xml"),x.getResponseHeader=function(e){var t={"content-type":m.dataType};return t[e]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var l=(m.dataType||"").toLowerCase(),c=/(json|script|text)/.test(l);if(c||m.textarea){var f=M.getElementsByTagName("textarea")[0];if(f)x.responseText=f.value,x.status=Number(f.getAttribute("status"))||x.status,x.statusText=f.getAttribute("statusText")||x.statusText;else if(c){var d=M.getElementsByTagName("pre")[0],h=M.getElementsByTagName("body")[0];d?x.responseText=d.textContent?d.textContent:d.innerText:h&&(x.responseText=h.textContent?h.textContent:h.innerText)}}else"xml"==l&&!x.responseXML&&x.responseText&&(x.responseXML=X(x.responseText));try{L=_(x,l,m)}catch(b){i="parsererror",x.error=r=b||i}}catch(b){a("error caught: ",b),i="error",x.error=r=b||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&300>x.status||304===x.status?"success":"error"),"success"===i?(m.success&&m.success.call(m.context,L,"success",x),S.resolve(x.responseText,"success",x),p&&e.event.trigger("ajaxSuccess",[x,m])):i&&(void 0===r&&(r=x.statusText),m.error&&m.error.call(m.context,x,i,r),S.reject(x,"error",r),p&&e.event.trigger("ajaxError",[x,m,r])),p&&e.event.trigger("ajaxComplete",[x,m]),p&&!--e.active&&e.event.trigger("ajaxStop"),m.complete&&m.complete.call(m.context,x,i),F=!0,m.timeout&&clearTimeout(j),setTimeout(function(){m.iframeTarget||v.remove(),x.responseXML=null},100)}}}var l,c,m,p,d,v,g,x,b,y,T,j,w=f[0],S=e.Deferred();if(r)for(c=0;h.length>c;c++)l=e(h[c]),i?l.prop("disabled",!1):l.removeAttr("disabled");if(m=e.extend(!0,{},e.ajaxSettings,t),m.context=m.context||m,d="jqFormIO"+(new Date).getTime(),m.iframeTarget?(v=e(m.iframeTarget),y=v.attr2("name"),y?d=y:v.attr2("name",d)):(v=e('<iframe name="'+d+'" src="'+m.iframeSrc+'" />'),v.css({position:"absolute",top:"-1000px",left:"-1000px"})),g=v[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{g.contentWindow.document.execCommand&&g.contentWindow.document.execCommand("Stop")}catch(n){}v.attr("src",m.iframeSrc),x.error=r,m.error&&m.error.call(m.context,x,r,t),p&&e.event.trigger("ajaxError",[x,m,r]),m.complete&&m.complete.call(m.context,x,r)}},p=m.global,p&&0===e.active++&&e.event.trigger("ajaxStart"),p&&e.event.trigger("ajaxSend",[x,m]),m.beforeSend&&m.beforeSend.call(m.context,x,m)===!1)return m.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;b=w.clk,b&&(y=b.name,y&&!b.disabled&&(m.extraData=m.extraData||{},m.extraData[y]=b.value,"image"==b.type&&(m.extraData[y+".x"]=w.clk_x,m.extraData[y+".y"]=w.clk_y)));var k=1,D=2,A=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&A&&(m.extraData=m.extraData||{},m.extraData[E]=A),m.forceSync?o():setTimeout(o,10);var L,M,F,O=50,X=e.parseXML||function(e,t){return window.ActiveXObject?(t=new ActiveXObject("Microsoft.XMLDOM"),t.async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!=t.documentElement.nodeName?t:null},C=e.parseJSON||function(e){return window.eval("("+e+")")},_=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i="xml"===r||!r&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&("json"===r||!r&&n.indexOf("json")>=0?o=C(o):("script"===r||!r&&n.indexOf("javascript")>=0)&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var u,l,c,f=this;"function"==typeof t&&(t={success:t}),u=t.type||this.attr2("method"),l=t.url||this.attr2("action"),c="string"==typeof l?e.trim(l):"",c=c||window.location.href||"",c&&(c=(c.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:c,success:e.ajaxSettings.success,type:u||"GET",iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&t.beforeSerialize(this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var p=t.traditional;void 0===p&&(p=e.ajaxSettings.traditional);var d,h=[],v=this.formToArray(t.semantic,h);if(t.data&&(t.extraData=t.data,d=e.param(t.data,p)),t.beforeSubmit&&t.beforeSubmit(v,this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[v,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var g=e.param(v,p);d&&(g=g?g+"&"+d:d),"GET"==t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+g,t.data=null):t.data=g;var x=[];if(t.resetForm&&x.push(function(){f.resetForm()}),t.clearForm&&x.push(function(){f.clearForm(t.includeHidden)}),!t.dataType&&t.target){var b=t.success||function(){};x.push(function(r){var a=t.replaceTarget?"replaceWith":"html";e(t.target)[a](r).each(b,arguments)})}else t.success&&x.push(t.success);if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=x.length;o>i;i++)x[i].apply(n,[e,r,a||f,f])},t.error){var y=t.error;t.error=function(e,r,a){var n=t.context||this;y.apply(n,[e,r,a,f])}}if(t.complete){var T=t.complete;t.complete=function(e,r){var a=t.context||this;T.apply(a,[e,r,f])}}var j=e('input[type=file]:enabled[value!=""]',this),w=j.length>0,S="multipart/form-data",k=f.attr("enctype")==S||f.attr("encoding")==S,D=n.fileapi&&n.formdata;a("fileAPI :"+D);var A,E=(w||k)&&!D;t.iframe!==!1&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){A=s(v)}):A=s(v):A=(w||k)&&D?o(v):e.ajax(t),f.removeData("jqxhr").data("jqxhr",A);for(var L=0;h.length>L;L++)h[L]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n){if(n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var i={s:this.selector,c:this.context};return!e.isReady&&i.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(i.s,i.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().bind("submit.form-plugin",n,t).bind("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.unbind("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r){var a=[];if(0===this.length)return a;var i=this[0],o=t?i.getElementsByTagName("*"):i.elements;if(!o)return a;var s,u,l,c,f,m,p;for(s=0,m=o.length;m>s;s++)if(f=o[s],l=f.name,l&&!f.disabled)if(t&&i.clk&&"image"==f.type)i.clk==f&&(a.push({name:l,value:e(f).val(),type:f.type}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}));else if(c=e.fieldValue(f,!0),c&&c.constructor==Array)for(r&&r.push(f),u=0,p=c.length;p>u;u++)a.push({name:l,value:c[u]});else if(n.fileapi&&"file"==f.type){r&&r.push(f);var d=f.files;if(d.length)for(u=0;d.length>u;u++)a.push({name:l,value:d[u],type:f.type});else a.push({name:l,value:"",type:f.type})}else null!==c&&c!==void 0&&(r&&r.push(f),a.push({name:l,value:c,type:f.type,required:f.required}));if(!t&&i.clk){var h=e(i.clk),v=h[0];l=v.name,l&&!v.disabled&&"image"==v.type&&(a.push({name:l,value:h.val()}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}))}return a},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor==Array)for(var i=0,o=n.length;o>i;i++)r.push({name:a,value:n[i]});else null!==n&&n!==void 0&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;n>a;a++){var i=this[a],o=e.fieldValue(i,t);null===o||void 0===o||o.constructor==Array&&!o.length||(o.constructor==Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,n=t.type,i=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"==n||"button"==n||("checkbox"==n||"radio"==n)&&!t.checked||("submit"==n||"image"==n)&&t.form&&t.form.clk!=t||"select"==i&&-1==t.selectedIndex))return null;if("select"==i){var o=t.selectedIndex;if(0>o)return null;for(var s=[],u=t.options,l="select-one"==n,c=l?o+1:u.length,f=l?o:0;c>f;f++){var m=u[f];if(m.selected){var p=m.value;if(p||(p=m.attributes&&m.attributes.value&&!m.attributes.value.specified?m.text:m.value),l)return p;s.push(p)}}return s}return e(t).val()},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"==n?this.value="":"checkbox"==a||"radio"==a?this.checked=!1:"select"==n?this.selectedIndex=-1:"file"==a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(t===!0&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")})},e.fn.resetForm=function(){return this.each(function(){("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset()})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"==r||"radio"==r)this.checked=t;else if("option"==this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"==a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1})(jQuery);
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        25. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (379 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 82920
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"82920-1230357900000"
          Last-Modified: Sat, 27 Dec 2008 06:05:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (82920 bytes)
          /*
           * jquery.layout 1.2.0
           *
           * Copyright (c) 2008 
           *   Fabrizio Balliano (http://www.fabrizioballiano.net)
           *   Kevin Dalman (http://allpro.net)
           *
           * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
           * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
           *
           * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
           * $Rev: 203 $
           * 
           * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
           */
          (function($) {
          
          $.fn.layout = function (opts) {
          
          /*
           * ###########################
           *   WIDGET CONFIG & OPTIONS
           * ###########################
           */
          
          	// DEFAULTS for options
          	var 
          		prefix = "ui-layout-" // prefix for ALL selectors and classNames
          	,	defaults = { //	misc default values
          			paneClass:				prefix+"pane"		// ui-layout-pane
          		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
          		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
          		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
          		,	buttonClass:			prefix+"button"		// ui-layout-button
          		,	contentSelector:		"."+prefix+"content"// ui-layout-content
          		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
          		}
          	;
          
          	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
          	var options = {
          		name:						""			// FUTURE REFERENCE - not used right now
          	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
          	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
          			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
          		,	closable:				true		// pane can open & close
          		,	resizable:				true		// when open, pane can be resized 
          		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
          		//,	paneSelector:			[ ]			// MUST be pane-specific!
          		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
          		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
          		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
          		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
          		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
          		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
          		,	resizerDragOpacity:		1			// option for ui.draggable
          		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
          		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
          		//,	size:					100			// inital size of pane - defaults are set 'per pane'
          		,	minSize:				0			// when manually resizing a pane
          		,	maxSize:				0			// ditto, 0 = no limit
          		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
          		,	spacing_closed:			6			// ditto - when pane is 'closed'
          		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
          		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
          		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
          		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
          		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
          		,	togglerTip_closed:		"Open"		// ditto
          		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
          		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
          		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
          		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
          		,	slideTrigger_close:		"mouseout"	// click, mouseout
          		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
          		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
          		,	togglerContent_closed:	""			// ditto
          		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
          		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
          		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
          		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
          		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
          		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
          		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
          		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
          		,	initClosed:				false		// true = init pane as 'closed'
          		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
          		
          		/*	callback options do not have to be set - listed here for reference only
          		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
          		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
          		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
          		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
          		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
          		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
          		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
          		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
          		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
          		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
          		*/
          		}
          	,	north: {
          			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
          		,	size:					"auto"
          		,	resizerCursor:			"n-resize"
          		}
          	,	south: {
          			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
          		,	size:					"auto"
          		,	resizerCursor:			"s-resize"
          		}
          	,	east: {
          			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
          		,	size:					200
          		,	resizerCursor:			"e-resize"
          		}
          	,	west: {
          			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
          		,	size:					200
          		,	resizerCursor:			"w-resize"
          		}
          	,	center: {
          			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
          		}
          
          	};
          
          
          	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
          		slide:	{
          			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	drop:	{
          			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	scale:	{
          			all:	{ duration:  "fast"	}
          		}
          	};
          
          
          	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
          	var config = {
          		allPanes:		"north,south,east,west,center"
          	,	borderPanes:	"north,south,east,west"
          	,	zIndex: { // set z-index values here
          			resizer_normal:	1		// normal z-index for resizer-bars
          		,	pane_normal:	2		// normal z-index for panes
          		,	mask:			4		// overlay div used to mask pane(s) during resizing
          		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
          		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
          		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
          		}
          	,	resizers: {
          			cssReq: {
          				position: 	"absolute"
          			,	padding: 	0
          			,	margin: 	0
          			,	fontSize:	"1px"
          			,	textAlign:	"left" // to counter-act "center" alignment!
          			,	overflow: 	"hidden" // keep toggler button from overflowing
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#DDD"
          			,	border:		"none"
          			}
          		}
          	,	togglers: {
          			cssReq: {
          				position: 	"absolute"
          			,	display: 	"block"
          			,	padding: 	0
          			,	margin: 	0
          			,	overflow:	"hidden"
          			,	textAlign:	"center"
          			,	fontSize:	"1px"
          			,	cursor: 	"pointer"
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#AAA"
          			}
          		}
          	,	content: {
          			cssReq: {
          				overflow:	"auto"
          			}
          		,	cssDef: {}
          		}
          	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
          			cssReq: {
          				position: 	"absolute"
          			,	margin:		0
          			,	zIndex: 	2
          			}
          		,	cssDef: {
          				padding:	"10px"
          			,	background:	"#FFF"
          			,	border:		"1px solid #BBB"
          			,	overflow:	"auto"
          			}
          		}
          	,	north: {
          			edge:			"top"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		0
          			,	bottom: 	"auto"
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	south: {
          			edge:			"bottom"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		"auto"
          			,	bottom: 	0
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	east: {
          			edge:			"right"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		"auto"
          			,	right: 		0
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	west: {
          			edge:			"left"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		0
          			,	right: 		"auto"
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	center: {
          			dir:			"center"
          		,	cssReq: {
          				left: 		"auto" // DYNAMIC
          			,	right: 		"auto" // DYNAMIC
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			,	width: 		"auto"
          			}
          		}
          	};
          
          
          	// DYNAMIC DATA
          	var state = {
          		// generate random 'ID#' to identify layout - used to create global namespace for timers
          		id:			Math.floor(Math.random() * 10000)
          	,	container:	{}
          	,	north:		{}
          	,	south:		{}
          	,	east:		{}
          	,	west:		{}
          	,	center:		{}
          	};
          
          
          	var 
          		altEdge = {
          			top:	"bottom"
          		,	bottom: "top"
          		,	left:	"right"
          		,	right:	"left"
          		}
          	,	altSide = {
          			north:	"south"
          		,	south:	"north"
          		,	east: 	"west"
          		,	west: 	"east"
          		}
          	;
          
          
          /*
           * ###########################
           *  INTERNAL HELPER FUNCTIONS
           * ###########################
           */
          
          	/**
          	 * isStr
          	 *
          	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
          	 */
          	var isStr = function (o) {
          		if (typeof o == "string")
          			return true;
          		else if (typeof o == "object") {
          			try {
          				var match = o.constructor.toString().match(/string/i); 
          				return (match !== null);
          			} catch (e) {} 
          		}
          		return false;
          	};
          
          	/**
          	 * str
          	 *
          	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
          	 *  else returns the original object
          	 */
          	var str = function (o) {
          		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
          		else return o;
          	};
          
          	/**
          	 * min / max
          	 *
          	 * Alias for Math.min/.max to simplify coding
          	 */
          	var min = function (x,y) { return Math.min(x,y); };
          	var max = function (x,y) { return Math.max(x,y); };
          
          	/**
          	 * transformData
          	 *
          	 * Processes the options passed in and transforms them into the format used by layout()
          	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
          	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
          	 * To update effects, options MUST use nested-keys format, with an effects key
          	 *
          	 * @callers  initOptions()
          	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
          	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
          	 */
          	var transformData = function (d) {
          		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
          		d = d || {};
          		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
          			json = $.extend( json, d ); // already in json format - add to base keys
          		else
          			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
          			$.each( d, function (key,val) {
          				a = key.split("__");
          				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
          			});
          		return json;
          	};
          
          	/**
          	 * setFlowCallback
          	 *
          	 * Set an INTERNAL callback to avoid simultaneous animation
          	 * Runs only if needed and only if all callbacks are not 'already set'!
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var setFlowCallback = function (action, pane, param) {
          		var
          			cb = action +","+ pane +","+ (param ? 1 : 0)
          		,	cP, cbPane
          		;
          		$.each(c.borderPanes.split(","), function (i,p) {
          			if (c[p].isMoving) {
          				bindCallback(p); // TRY to bind a callback
          				return false; // BREAK
          			}
          		});
          
          		function bindCallback (p, test) {
          			cP = c[p];
          			if (!cP.doCallback) {
          				cP.doCallback = true;
          				cP.callback = cb;
          			}
          			else { // try to 'chain' this callback
          				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
          				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
          					bindCallback (cpPane, true); // RECURSE
          			}
          		}
          	};
          
          	/**
          	 * execFlowCallback
          	 *
          	 * RUN the INTERNAL callback for this pane - if one exists
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var execFlowCallback = function (pane) {
          		var cP = c[pane];
          
          		// RESET flow-control flaGs
          		c.isLayoutBusy = false;
          		delete cP.isMoving;
          		if (!cP.doCallback || !cP.callback) return;
          
          		cP.doCallback = false; // RESET logic flag
          
          		// EXECUTE the callback
          		var
          			cb = cP.callback.split(",")
          		,	param = (cb[2] > 0 ? true : false)
          		;
          		if (cb[0] == "open")
          			open( cb[1], param  );
          		else if (cb[0] == "close")
          			close( cb[1], param );
          
          		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
          	};
          
          	/**
          	 * execUserCallback
          	 *
          	 * Executes a Callback function after a trigger event, like resize, open or close
          	 *
          	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
          	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
          	 */
          	var execUserCallback = function (pane, v_fn) {
          		if (!v_fn) return;
          		var fn;
          		try {
          			if (typeof v_fn == "function")
          				fn = v_fn;	
          			else if (typeof v_fn != "string")
          				return;
          			else if (v_fn.indexOf(",") > 0) {
          				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
          				var
          					args = v_fn.split(",")
          				,	fn = eval(args[0])
          				;
          				if (typeof fn=="function" && args.length > 1)
          					return fn(args[1]); // pass the argument parsed from 'list'
          			}
          			else // just the name of an external function?
          				fn = eval(v_fn);
          
          			if (typeof fn=="function")
          				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
          				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
          		}
          		catch (ex) {}
          	};
          
          	/**
          	 * cssNum
          	 *
          	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
          	 *
          	 * @callers  Called by many methods
          	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
          	 * @param String  property  The name of the CSS property, eg: top, width, etc.
          	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
          	 */
          	var cssNum = function ($E, prop) {
          		var
          			val = 0
          		,	hidden = false
          		,	visibility = ""
          		;
          		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
          			if ($.curCSS($E[0], "display", true) == "none") {
          				hidden = true;
          				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
          				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
          			}
          		}
          
          		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
          
          		if (hidden) { // WAS hidden, so put back the way it was
          			$E.css({ display: "none" });
          			if (visibility && visibility != "hidden")
          				$E.css({ visibility: visibility }); // reset 'visibility'
          		}
          
          		return val;
          	};
          
          	/**
          	 * cssW / cssH / cssSize
          	 *
          	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
          	 *
          	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
          	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
          	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
          	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
          	 *
          	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
          	 */
          	var cssW = function (e, outerWidth) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerWidth <= 0)
          			return 0;
          		else if (!(outerWidth>0))
          			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
          
          		if (!$.boxModel)
          			return outerWidth;
          
          		else // strip border and padding size from outerWidth to get CSS Width
          			return outerWidth
          				- cssNum($E, "paddingLeft")		
          				- cssNum($E, "paddingRight")
          				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
          				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
          			;
          	};
          	var cssH = function (e, outerHeight) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerHeight <= 0)
          			return 0;
          		else if (!(outerHeight>0))
          			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
          
          		if (!$.boxModel)
          			return outerHeight;
          
          		else // strip border and padding size from outerHeight to get CSS Height
          			return outerHeight
          				- cssNum($E, "paddingTop")
          				- cssNum($E, "paddingBottom")
          				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
          				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
          			;
          	};
          	var cssSize = function (pane, outerSize) {
          		if (c[pane].dir=="horz") // pane = north or south
          			return cssH(pane, outerSize);
          		else // pane = east or west
          			return cssW(pane, outerSize);
          	};
          
          	/**
          	 * getPaneSize
          	 *
          	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
          	 *
          	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
          	 */
          	var getPaneSize = function (pane, inclSpace) {
          		var 
          			$P	= $Ps[pane]
          		,	o	= options[pane]
          		,	s	= state[pane]
          		,	oSp	= (inclSpace ? o.spacing_open : 0)
          		,	cSp	= (inclSpace ? o.spacing_closed : 0)
          		;
          		if (!$P || s.isHidden)
          			return 0;
          		else if (s.isClosed || (s.isSliding && inclSpace))
          			return cSp;
          		else if (c[pane].dir == "horz")
          			return $P.outerHeight() + oSp;
          		else // dir == "vert"
          			return $P.outerWidth() + oSp;
          	};
          
          	var setPaneMinMaxSizes = function (pane) {
          		var 
          			d				= cDims
          		,	edge			= c[pane].edge
          		,	dir				= c[pane].dir
          		,	o				= options[pane]
          		,	s				= state[pane]
          		,	$P				= $Ps[pane]
          		,	$altPane		= $Ps[ altSide[pane] ]
          		,	paneSpacing		= o.spacing_open
          		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
          		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
          		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
          		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
          		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
          		,	minSize			= s.minSize || 0
          		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
          		,	minPos, maxPos	// used to set resizing limits
          		;
          		switch (pane) {
          			case "north":	minPos = d.offsetTop + minSize;
          							maxPos = d.offsetTop + maxSize;
          							break;
          			case "west":	minPos = d.offsetLeft + minSize;
          							maxPos = d.offsetLeft + maxSize;
          							break;
          			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
          							maxPos = d.offsetTop + d.innerHeight - minSize;
          							break;
          			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
          							maxPos = d.offsetLeft + d.innerWidth - minSize;
          							break;
          		}
          		// save data to pane-state
          		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
          	};
          
          	/**
          	 * getPaneDims
          	 *
          	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
          	 *
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
          	 */
          	var getPaneDims = function () {
          		var d = {
          			top:	getPaneSize("north", true) // true = include 'spacing' value for p
          		,	bottom:	getPaneSize("south", true)
          		,	left:	getPaneSize("west", true)
          		,	right:	getPaneSize("east", true)
          		,	width:	0
          		,	height:	0
          		};
          
          		with (d) {
          			width 	= cDims.innerWidth - left - right;
          			height 	= cDims.innerHeight - bottom - top;
          			// now add the 'container border/padding' to get final positions - relative to the container
          			top		+= cDims.top;
          			bottom	+= cDims.bottom;
          			left	+= cDims.left;
          			right	+= cDims.right;
          		}
          
          		return d;
          	};
          
          
          	/**
          	 * getElemDims
          	 *
          	 * Returns data for setting size of an element (container or a pane).
          	 *
          	 * @callers  create(), onWindowResize() for container, plus others for pane
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
          	 */
          	var getElemDims = function ($E) {
          		var
          			d = {} // dimensions hash
          		,	e, b, p // edge, border, padding
          		;
          
          		$.each("Left,Right,Top,Bottom".split(","), function () {
          			e = str(this);
          			b = d["border" +e] = cssNum($E, "border"+e+"Width");
          			p = d["padding"+e] = cssNum($E, "padding"+e);
          			d["offset" +e] = b + p; // total offset of content from outer edge
          			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
          			if ($E == $Container)
          				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
          		});
          
          		d.innerWidth  = d.outerWidth  = $E.outerWidth();
          		d.innerHeight = d.outerHeight = $E.outerHeight();
          		if ($.boxModel) {
          			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
          			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
          		}
          
          		return d;
          	};
          
          
          	var setTimer = function (pane, action, fn, ms) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) return; // timer already set!
          		else Timers[name] = setTimeout(fn, ms);
          	};
          
          	var clearTimer = function (pane, action) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) {
          			clearTimeout( Timers[name] );
          			delete Timers[name];
          			return true;
          		}
          		else
          			return false;
          	};
          
          
          /*
           * ###########################
           *   INITIALIZATION METHODS
           * ###########################
           */
          
          	/**
          	 * create
          	 *
          	 * Initialize the layout - called automatically whenever an instance of layout is created
          	 *
          	 * @callers  NEVER explicity called
          	 * @returns  An object pointer to the instance created
          	 */
          	var create = function () {
          		// initialize config/options
          		initOptions();
          
          		// initialize all objects
          		initContainer();	// set CSS as needed and init state.container dimensions
          		initPanes();		// size & position all panes
          		initHandles();		// create and position all resize bars & togglers buttons
          		initResizable();	// activate resizing on all panes where resizable=true
          		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
          
          		if (options.scrollToBookmarkOnLoad)
          			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
          
          		// bind hotkey function - keyDown - if required
          		initHotkeys();
          
          		// bind resizeAll() for 'this layout instance' to window.resize event
          		$(window).resize(function () {
          			var timerID = "timerLayout_"+state.id;
          			if (window[timerID]) clearTimeout(window[timerID]);
          			window[timerID] = null;
          			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
          				window[timerID] = setTimeout(resizeAll, 100);
          			else // most other browsers have a built-in delay before firing the resize event
          				resizeAll(); // resize all layout elements NOW!
          		});
          	};
          
          	/**
          	 * initContainer
          	 *
          	 * Validate and initialize container CSS and events
          	 *
          	 * @callers  create()
          	 */
          	var initContainer = function () {
          		try { // format html/body if this is a full page layout
          			if ($Container[0].tagName == "BODY") {
          				$("html").css({
          					height:		"100%"
          				,	overflow:	"hidden"
          				});
          				$("body").css({
          					position:	"relative"
          				,	height:		"100%"
          				,	overflow:	"hidden"
          				,	margin:		0
          				,	padding:	0		// TODO: test whether body-padding could be handled?
          				,	border:		"none"	// a body-border creates problems because it cannot be measured!
          				});
          			}
          			else { // set required CSS - overflow and position
          				var
          					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
          				,	p	= $Container.css("position")
          				,	h	= $Container.css("height")
          				;
          				// if this is a NESTED layout, then outer-pane ALREADY has position and height
          				if (!$Container.hasClass("ui-layout-pane")) {
          					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
          						CSS.position = "relative"; // container MUST have a 'position'
          					if (!h || h=="auto")
          						CSS.height = "100%"; // container MUST have a 'height'
          				}
          				$Container.css( CSS );
          			}
          		} catch (ex) {}
          
          		// get layout-container dimensions (updated when necessary)
          		cDims = state.container = getElemDims( $Container ); // update data-pointer too
          	};
          
          	/**
          	 * initHotkeys
          	 *
          	 * Bind layout hotkeys - if options enabled
          	 *
          	 * @callers  create()
          	 */
          	var initHotkeys = function () {
          		// bind keyDown to capture hotkeys, if option enabled for ANY pane
          		$.each(c.borderPanes.split(","), function (i,pane) {
          			var o = options[pane];
          			if (o.enableCursorHotkey || o.customHotkey) {
          				$(document).keydown( keyDown ); // only need to bind this ONCE
          				return false; // BREAK - binding was done
          			}
          		});
          	};
          
          	/**
          	 * initOptions
          	 *
          	 * Build final CONFIG and OPTIONS data
          	 *
          	 * @callers  create()
          	 */
          	var initOptions = function () {
          		// simplify logic by making sure passed 'opts' var has basic keys
          		opts = transformData( opts );
          
          		// update default effects, if case user passed key
          		if (opts.effects) {
          			$.extend( effects, opts.effects );
          			delete opts.effects;
          		}
          
          		// see if any 'global options' were specified
          		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
          			if (opts[key] !== undefined)
          				options[key] = opts[key];
          			else if (opts.defaults[key] !== undefined) {
          				options[key] = opts.defaults[key];
          				delete opts.defaults[key];
          			}
          		});
          
          		// remove any 'defaults' that MUST be set 'per-pane'
          		$.each("paneSelector,resizerCursor,customHotkey".split(","),
          			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
          		);
          
          		// now update options.defaults
          		$.extend( options.defaults, opts.defaults );
          		// make sure required sub-keys exist
          		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
          
          		// merge all config & options for the 'center' pane
          		c.center = $.extend( true, {}, c.defaults, c.center );
          		$.extend( options.center, opts.center );
          		// Most 'default options' do not apply to 'center', so add only those that DO
          		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
          		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
          			function (idx,key) { options.center[key] = o_Center[key]; }
          		);
          
          		var defs = options.defaults;
          
          		// create a COMPLETE set of options for EACH border-pane
          		$.each(c.borderPanes.split(","), function(i,pane) {
          			// apply 'pane-defaults' to CONFIG.PANE
          			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
          			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
          			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
          
          			// make sure we have base-classes
          			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
          			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
          			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
          
          			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
          			$.each(["_open","_close",""], function (i,n) { 
          				var
          					sName		= "fxName"+n
          				,	sSpeed		= "fxSpeed"+n
          				,	sSettings	= "fxSettings"+n
          				;
          				// recalculate fxName according to specificity rules
          				o[sName] =
          					opts[pane][sName]		// opts.west.fxName_open
          				||	opts[pane].fxName		// opts.west.fxName
          				||	opts.defaults[sName]	// opts.defaults.fxName_open
          				||	opts.defaults.fxName	// opts.defaults.fxName
          				||	o[sName]				// options.west.fxName_open
          				||	o.fxName				// options.west.fxName
          				||	defs[sName]				// options.defaults.fxName_open
          				||	defs.fxName				// options.defaults.fxName
          				||	"none"
          				;
          				// validate fxName to be sure is a valid effect
          				var fxName = o[sName];
          				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
          					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
          				// set vars for effects subkeys to simplify logic
          				var
          					fx = effects[fxName]	|| {} // effects.slide
          				,	fx_all	= fx.all		|| {} // effects.slide.all
          				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
          				;
          				// RECREATE the fxSettings[_open|_close] keys using specificity rules
          				o[sSettings] = $.extend(
          					{}
          				,	fx_all						// effects.slide.all
          				,	fx_pane						// effects.slide.west
          				,	defs.fxSettings || {}		// options.defaults.fxSettings
          				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
          				,	o.fxSettings				// options.west.fxSettings
          				,	o[sSettings]				// options.west.fxSettings_open
          				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
          				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
          				,	opts[pane].fxSettings		// opts.west.fxSettings
          				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
          				);
          				// recalculate fxSpeed according to specificity rules
          				o[sSpeed] =
          					opts[pane][sSpeed]		// opts.west.fxSpeed_open
          				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
          				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
          				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
          				||	o[sSpeed]				// options.west.fxSpeed_open
          				||	o[sSettings].duration	// options.west.fxSettings_open.duration
          				||	o.fxSpeed				// options.west.fxSpeed
          				||	o.fxSettings.duration	// options.west.fxSettings.duration
          				||	defs.fxSpeed			// options.defaults.fxSpeed
          				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
          				||	fx_pane.duration		// effects.slide.west.duration
          				||	fx_all.duration			// effects.slide.all.duration
          				||	"normal"				// DEFAULT
          				;
          				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
          			});
          		});
          	};
          
          	/**
          	 * initPanes
          	 *
          	 * Initialize module objects, styling, size and position for all panes
          	 *
          	 * @callers  create()
          	 */
          	var initPanes = function () {
          		// NOTE: do north & south FIRST so we can measure their height - do center LAST
          		$.each(c.allPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	fx		= s.fx
          			,	dir		= c[pane].dir
          			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
          			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
          			,	minSize	= o.minSize || 1
          			,	maxSize	= o.maxSize || 9999
          			,	spacing	= o.spacing_open || 0
          			,	sel		= o.paneSelector
          			,	isIE6	= ($.browser.msie && $.browser.version < 7)
          			,	CSS		= {}
          			,	$P, $C
          			;
          			$Cs[pane] = false; // init
          
          			if (sel.substr(0,1)==="#") // ID selector
          				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
          				$P = $Ps[pane] = $Container.find(sel+":first");
          			else { // class or other selector
          				$P = $Ps[pane] = $Container.children(sel+":first");
          				// look for the pane nested inside a 'form' element
          				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
          			}
          
          			if (!$P.length) {
          				$Ps[pane] = false; // logic
          				return true; // SKIP to next
          			}
          
          			// add basic classes & attributes
          			$P
          				.attr("pane", pane) // add pane-identifier
          				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
          			;
          
          			// init pane-logic vars, etc.
          			if (pane != "center") {
          				s.isClosed  = false; // true = pane is closed
          				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
          				s.isResizing= false; // true = pane is in process of being resized
          				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
          				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
          				// create special keys for internal use
          				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
          			}
          
          			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
          			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
          			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
          			CSS = {};	// reset var
          
          			// set css-position to account for container borders & padding
          			switch (pane) {
          				case "north": 	CSS.top 	= cDims.top;
          								CSS.left 	= cDims.left;
          								CSS.right	= cDims.right;
          								break;
          				case "south": 	CSS.bottom	= cDims.bottom;
          								CSS.left 	= cDims.left;
          								CSS.right 	= cDims.right;
          								break;
          				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
          								break;
          				case "east": 	CSS.right 	= cDims.right; // ditto
          								break;
          				case "center":	// top, left, width & height set by sizeMidPanes()
          			}
          
          			if (dir == "horz") { // north or south pane
          				if (size === 0 || size == "auto") {
          					$P.css({ height: "auto" });
          					size = $P.outerHeight();
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerHeight - spacing);
          				CSS.height = max(1, cssH(pane, size));
          				s.size = size; // update state
          				// make sure minSize is sufficient to avoid errors
          				s.maxSize = maxSize; // init value
          				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
          				// handle IE6
          				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
          				$P.css(CSS); // apply size & position
          			}
          			else if (dir == "vert") { // east or west pane
          				if (size === 0 || size == "auto") {
          					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
          					size = $P.outerWidth();
          					$P.css({ float: "none" }); // RESET
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerWidth - spacing);
          				CSS.width = max(1, cssW(pane, size));
          				s.size = size; // update state
          				s.maxSize = maxSize; // init value
          				// make sure minSize is sufficient to avoid errors
          				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
          				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
          				sizeMidPanes(pane, null, true); // true = onInit
          			}
          			else if (pane == "center") {
          				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
          				sizeMidPanes("center", null, true); // true = onInit
          			}
          
          			// close or hide the pane if specified in settings
          			if (o.initClosed && o.closable) {
          				$P.hide().addClass("closed");
          				s.isClosed = true;
          			}
          			else if (o.initHidden || o.initClosed) {
          				hide(pane, true); // will be completely invisible - no resizer or spacing
          				s.isHidden = true;
          			}
          			else
          				$P.addClass("open");
          
          			// check option for auto-handling of pop-ups & drop-downs
          			if (o.showOverflowOnHover)
          				$P.hover( allowOverflow, resetOverflow );
          
          			/*
          			 *	see if this pane has a 'content element' that we need to auto-size
          			 */
          			if (o.contentSelector) {
          				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
          				if (!$C.length) {
          					$Cs[pane] = false;
          					return true; // SKIP to next
          				}
          				$C.css( c.content.cssReq );
          				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
          				// NO PANE-SCROLLING when there is a content-div
          				$P.css({ overflow: "hidden" });
          			}
          		});
          	};
          
          	/**
          	 * initHandles
          	 *
          	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
          	 *
          	 * @callers  create()
          	 */
          	var initHandles = function () {
          		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	rClass	= o.resizerClass
          			,	tClass	= o.togglerClass
          			,	$P		= $Ps[pane]
          			;
          			$Rs[pane] = false; // INIT
          			$Ts[pane] = false;
          
          			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
          
          			var 
          				edge	= c[pane].edge
          			,	isOpen	= $P.is(":visible")
          			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
          			,	_pane	= "-"+ pane // used for classNames
          			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
          			,	$R, $T
          			;
          			// INIT RESIZER BAR
          			$R = $Rs[pane] = $("<span></span>");
          	
          			if (isOpen && o.resizable)
          				; // this is handled by initResizable
          			else if (!isOpen && o.slidable)
          				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
          	
          			$R
          				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
          				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
          				.attr("resizer", pane) // so we can read this from the resizer
          				.css(c.resizers.cssReq) // add base/required styles
          				// POSITION of resizer bar - allow for container border & padding
          				.css(edge, cDims[edge] + getPaneSize(pane))
          				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
          				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
          				.appendTo($Container) // append DIV to container
          			;
          			 // ADD VISUAL STYLES
          			if (o.applyDefaultStyles)
          				$R.css(c.resizers.cssDef);
          
          			if (o.closable) {
          				// INIT COLLAPSER BUTTON
          				$T = $Ts[pane] = $("<div></div>");
          				$T
          					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
          					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
          					.css(c.togglers.cssReq) // add base/required styles
          					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
          					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
          					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
          					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
          					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
          					.appendTo($R) // append SPAN to resizer DIV
          				;
          
          				// ADD INNER-SPANS TO TOGGLER
          				if (o.togglerContent_open) // ui-layout-open
          					$("<span>"+ o.togglerContent_open +"</span>")
          						.addClass("content content-open")
          						.css("display", s.isClosed ? "none" : "block")
          						.appendTo( $T )
          					;
          				if (o.togglerContent_closed) // ui-layout-closed
          					$("<span>"+ o.togglerContent_closed +"</span>")
          						.addClass("content content-closed")
          						.css("display", s.isClosed ? "block" : "none")
          						.appendTo( $T )
          					;
          
          				 // ADD BASIC VISUAL STYLES
          				if (o.applyDefaultStyles)
          					$T.css(c.togglers.cssDef);
          
          				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          			}
          
          		});
          
          		// SET ALL HANDLE SIZES & LENGTHS
          		sizeHandles("all", true); // true = onInit
          	};
          
          	/**
          	 * initResizable
          	 *
          	 * Add resize-bars to all panes that specify it in options
          	 *
          	 * @dependancies  $.fn.resizable - will abort if not found
          	 * @callers  create()
          	 */
          	var initResizable = function () {
          		var
          			draggingAvailable = (typeof $.fn.draggable == "function")
          		,	minPosition, maxPosition, edge // set in start()
          		;
          
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			;
          			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
          				o.resizable = false;
          				return true; // skip to next
          			}
          
          			var 
          				rClass				= o.resizerClass
          			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
          			,	dragClass			= rClass+"-drag"			// resizer-drag
          			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
          			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
          			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
          			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
          			,	draggingClassSet	= false 					// logic var
          			,	$P 					= $Ps[pane]
          			,	$R					= $Rs[pane]
          			;
          
          			if (!s.isClosed)
          				$R
          					.attr("title", o.resizerTip)
          					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
          				;
          
          			$R.draggable({
          				containment:	$Container[0] // limit resizing to layout container
          			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
          			,	delay:			200
          			,	distance:		1
          			//	basic format for helper - style it using class: .ui-draggable-dragging
          			,	helper:			"clone"
          			,	opacity:		o.resizerDragOpacity
          			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
          			,	zIndex:			c.zIndex.resizing
          
          			,	start: function (e, ui) {
          					// onresize_start callback - will CANCEL hide if returns false
          					// TODO: CONFIRM that dragging can be cancelled like this???
          					if (false === execUserCallback(pane, o.onresize_start)) return false;
          
          					s.isResizing = true; // prevent pane from closing while resizing
          					clearTimer(pane, "closeSlider"); // just in case already triggered
          
          					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
          					draggingClassSet = false; // reset logic var - see drag()
          
          					// SET RESIZING LIMITS - used in drag()
          					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
          					setPaneMinMaxSizes(pane); // update pane-state
          					s.minPosition -= resizerWidth;
          					s.maxPosition -= resizerWidth;
          					edge = (c[pane].dir=="horz" ? "top" : "left");
          
          					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
          					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
          						$('<div class="ui-layout-mask"/>')
          							.css({
          								background:	"#fff"
          							,	opacity:	"0.001"
          							,	zIndex:		9
          							,	position:	"absolute"
          							,	width:		this.offsetWidth+"px"
          							,	height:		this.offsetHeight+"px"
          							})
          							.css($(this).offset()) // top & left
          							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
          						;
          					});
          				}
          
          			,	drag: function (e, ui) {
          					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
          						$(".ui-draggable-dragging")
          							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
          							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
          						;
          						draggingClassSet = true;
          						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
          						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
          					}
          					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
          					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
          					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
          				}
          
          			,	stop: function (e, ui) {
          					var 
          						dragPos	= ui.position
          					,	resizerPos
          					,	newSize
          					;
          					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
          	
          					switch (pane) {
          						case "north":	resizerPos = dragPos.top; break;
          						case "west":	resizerPos = dragPos.left; break;
          						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
          						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
          					}
          					// remove container margin from resizer position to get the pane size
          					newSize = resizerPos - cDims[ c[pane].edge ];
          
          					sizePane(pane, newSize);
          
          					// UN-MASK PANES MASKED IN drag.start
          					$("div.ui-layout-mask").remove(); // Remove iframe masks	
          
          					s.isResizing = false;
          				}
          
          			});
          		});
          	};
          
          
          
          /*
           * ###########################
           *       ACTION METHODS
           * ###########################
           */
          
          	/**
          	 * hide / show
          	 *
          	 * Completely 'hides' a pane, including its spacing - as if it does not exist
          	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
          	 *
          	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
          	 */
          	var hide = function (pane, onInit) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onhide_start)) return;
          
          		s.isSliding = false; // just in case
          
          		// now hide the elements
          		if ($R) $R.hide(); // hide resizer-bar
          		if (onInit || s.isClosed) {
          			s.isClosed = true; // to trigger open-animation on show()
          			s.isHidden  = true;
          			$P.hide(); // no animation when loading page
          			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          			execUserCallback(pane, o.onhide_end || o.onhide);
          		}
          		else {
          			s.isHiding = true; // used by onclose
          			close(pane, false); // adjust all panes to fit
          			//s.isHidden  = true; - will be set by close - if not cancelled
          		}
          	};
          
          	var show = function (pane, openPane) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onshow_start)) return;
          
          		s.isSliding = false; // just in case
          		s.isShowing = true; // used by onopen/onclose
          		//s.isHidden  = false; - will be set by open/close - if not cancelled
          
          		// now show the elements
          		if ($R && o.spacing_open > 0) $R.show();
          		if (openPane === false)
          			close(pane, true); // true = force
          		else
          			open(pane); // adjust all panes to fit
          	};
          
          
          	/**
          	 * toggle
          	 *
          	 * Toggles a pane open/closed by calling either open or close
          	 *
          	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
          	 */
          	var toggle = function (pane) {
          		var s = state[pane];
          		if (s.isHidden)
          			show(pane); // will call 'open' after unhiding it
          		else if (s.isClosed)
          			open(pane);
          		else
          			close(pane);
          	};
          
          	/**
          	 * close
          	 *
          	 * Close the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being closed, ie: north, south, east, or west
          	 */
          	var close = function (pane, force, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_sliding= "-sliding"
          		,	_closed	= "-closed"
          		// 	transfer logic vars to temp vars
          		,	isShowing = s.isShowing
          		,	isHiding = s.isHiding
          		;
          		// now clear the logic vars
          		delete s.isShowing;
          		delete s.isHiding;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!force && s.isClosed && !isShowing) return; // already closed
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("close", pane, force); // set a callback for this action, if possible
          			return; // ABORT 
          		}
          
          		// onclose_start callback - will CANCEL hide if returns false
          		// SKIP if just 'showing' a hidden pane as 'closed'
          		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		s.isClosed = true;
          		// update isHidden BEFORE sizing panes
          		if (isHiding) s.isHidden = true;
          		else if (isShowing) s.isHidden = false;
          
          		// sync any 'pin buttons'
          		syncPinBtns(pane, false);
          
          		// resize panes adjacent to this one
          		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          
          		// if this pane has a resizer bar, move it now
          		if ($R) {
          			$R
          				.css(edge, cDims[edge]) // move the resizer bar
          				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
          				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
          				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
          			;
          			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
          			if (o.resizable)
          				$R
          					.draggable("disable")
          					.css("cursor", "default")
          					.attr("title","")
          				;
          			// if pane has a toggler button, adjust that too
          			if ($T) {
          				$T
          					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
          					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
          					.attr("title", o.togglerTip_closed) // may be blank
          				;
          			}
          			sizeHandles(); // resize 'length' and position togglers for adjacent panes
          		}
          
          		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
          		if (doFX) {
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
          				lockPaneForFX(pane, false); // undo
          				if (!s.isClosed) return; // pane was opened before animation finished!
          				close_2();
          			});
          		}
          		else {
          			$P.hide(); // just hide pane NOW
          			close_2();
          		}
          
          		// SUBROUTINE
          		function close_2 () {
          			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          
          			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
          			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
          			// onhide OR onshow callback
          			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
          			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          
          	/**
          	 * open
          	 *
          	 * Open the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being opened, ie: north, south, east, or west
          	 */
          	var open = function (pane, slide, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_closed	= "-closed"
          		,	_sliding= "-sliding"
          		// 	transfer logic var to temp var
          		,	isShowing = s.isShowing
          		;
          		// now clear the logic var
          		delete s.isShowing;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!s.isClosed && !s.isSliding) return; // already open
          
          		// pane can ALSO be unhidden by just calling show(), so handle this scenario
          		if (s.isHidden && !isShowing) {
          			show(pane, true);
          			return;
          		}
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
          			return; // ABORT
          		}
          
          		// onopen_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onopen_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		// 'PIN PANE' - stop sliding
          		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
          			bindStopSlidingEvents(pane, false); // will set isSliding=false
          
          		s.isClosed = false;
          		// update isHidden BEFORE sizing panes
          		if (isShowing) s.isHidden = false;
          
          		// Container size may have changed - shrink the pane if now 'too big'
          		setPaneMinMaxSizes(pane); // update pane-state
          		if (s.size > s.maxSize) // pane is too big! resize it before opening
          			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
          
          		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
          
          		if (doFX) { // ANIMATE
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
          				lockPaneForFX(pane, false); // undo
          				if (s.isClosed) return; // pane was closed before animation finished!
          				open_2(); // continue
          			});
          		}
          		else {// no animation
          			$P.show();	// just show pane and...
          			open_2();	// continue
          		}
          
          		// SUBROUTINE
          		function open_2 () {
          			// NOTE: if isSliding, then other panes are NOT 'resized'
          			if (!s.isSliding) // resize all panes adjacent to this one
          				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
          
          			// if this pane has a toggler, move it now
          			if ($R) {
          				$R
          					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
          					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
          					.addClass( rClass+_open +" "+ rClass+_pane+_open )
          					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
          				;
          				if (o.resizable)
          					$R
          						.draggable("enable")
          						.css("cursor", o.resizerCursor)
          						.attr("title", o.resizerTip)
          					;
          				else
          					$R.css("cursor", "default"); // n-resize, s-resize, etc
          				// if pane also has a toggler button, adjust that too
          				if ($T) {
          					$T
          						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
          						.addClass( tClass+_open +" "+ tClass+_pane+_open )
          						.attr("title", o.togglerTip_open) // may be blank
          					;
          				}
          				sizeHandles("all"); // resize resizer & toggler sizes for all panes
          			}
          
          			// resize content every time pane opens - to be sure
          			sizeContent(pane);
          
          			// sync any 'pin buttons'
          			syncPinBtns(pane, !s.isSliding);
          
          			// onopen callback
          			execUserCallback(pane, o.onopen_end || o.onopen);
          
          			// onshow callback
          			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          	
          
          	/**
          	 * lockPaneForFX
          	 *
          	 * Must set left/top on East/South panes so animation will work properly
          	 *
          	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
          	 * @param Boolean  doLock  true = set left/top, false = remove
          	 */
          	var lockPaneForFX = function (pane, doLock) {
          		var $P = $Ps[pane];
          		if (doLock) {
          			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
          			if (pane=="south")
          				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
          			else if (pane=="east")
          				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
          		}
          		else {
          			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
          			if (pane=="south")
          				$P.css({ top: "auto" });
          			else if (pane=="east")
          				$P.css({ left: "auto" });
          		}
          	};
          
          
          	/**
          	 * bindStartSlidingEvent
          	 *
          	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
          	 *
          	 * @callers  open(), close()
          	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
          	 * @param Boolean  enable  Enable or Disable sliding?
          	 */
          	var bindStartSlidingEvent = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	$R		= $Rs[pane]
          		,	trigger	= o.slideTrigger_open
          		;
          		if (!$R || !o.slidable) return;
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
          		$R
          			// add or remove trigger event
          			[enable ? "bind" : "unbind"](trigger, slideOpen)
          			// set the appropriate cursor & title/tip
          			.css("cursor", (enable ? o.sliderCursor: "default"))
          			.attr("title", (enable ? o.sliderTip : ""))
          		;
          	};
          
          	/**
          	 * bindStopSlidingEvents
          	 *
          	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
          	 * Also increases zIndex when pane is sliding open
          	 * See bindStartSlidingEvent for code to control 'slide open'
          	 *
          	 * @callers  slideOpen(), slideClosed()
          	 * @param String  pane  The pane to process, 'north', 'south', etc.
          	 * @param Boolean  isOpen  Is pane open or closed?
          	 */
          	var bindStopSlidingEvents = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	s		= state[pane]
          		,	trigger	= o.slideTrigger_close
          		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          
          		s.isSliding = enable; // logic
          		clearTimer(pane, "closeSlider"); // just in case
          
          		// raise z-index when sliding
          		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
          		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
          
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
          
          		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
          		if (enable) { // BIND trigger events
          			$P.bind(trigger, slideClosed );
          			$R.bind(trigger, slideClosed );
          			if (trigger = "mouseout") {
          				$P.bind("mouseover", cancelMouseOut );
          				$R.bind("mouseover", cancelMouseOut );
          			}
          		}
          		else { // UNBIND trigger events
          			// TODO: why does unbind of a 'single function' not work reliably?
          			//$P[action](trigger, slideClosed );
          			$P.unbind(trigger);
          			$R.unbind(trigger);
          			if (trigger = "mouseout") {
          				//$P[action]("mouseover", cancelMouseOut );
          				$P.unbind("mouseover");
          				$R.unbind("mouseover");
          				clearTimer(pane, "closeSlider");
          			}
          		}
          
          		// SUBROUTINE for mouseout timer clearing
          		function cancelMouseOut (evt) {
          			clearTimer(pane, "closeSlider");
          			evt.stopPropagation();
          		}
          	};
          
          	var slideOpen = function () {
          		var pane = $(this).attr("resizer"); // attr added by initHandles
          		if (state[pane].isClosed) { // skip if already open!
          			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
          			open(pane, true); // true = slide - ie, called from here!
          		}
          	};
          
          	var slideClosed = function () {
          		var
          			$E = $(this)
          		,	pane = $E.attr("pane") || $E.attr("resizer")
          		,	o = options[pane]
          		,	s = state[pane]
          		;
          		if (s.isClosed || s.isResizing)
          			return; // skip if already closed OR in process of resizing
          		else if (o.slideTrigger_close == "click")
          			close_NOW(); // close immediately onClick
          		else // trigger = mouseout - use a delay
          			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
          
          		// SUBROUTINE for timed close
          		function close_NOW () {
          			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
          			if (!s.isClosed) close(pane); // skip if already closed!
          		}
          	};
          
          
          	/**
          	 * sizePane
          	 *
          	 * @callers  initResizable.stop()
          	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
          	 * @param Integer  newSize  The new size for this pane - will be validated
          	 */
          	var sizePane = function (pane, size) {
          		// TODO: accept "auto" as size, and size-to-fit pane content
          		var 
          			edge	= c[pane].edge
          		,	dir		= c[pane].dir
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          		// calculate 'current' min/max sizes
          		setPaneMinMaxSizes(pane); // update pane-state
          		// compare/update calculated min/max to user-options
          		s.minSize = max(s.minSize, o.minSize);
          		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
          		// validate passed size
          		size = max(size, s.minSize);
          		size = min(size, s.maxSize);
          		s.size = size; // update state
          
          		// move the resizer bar and resize the pane
          		$R.css( edge, size + cDims[edge] );
          		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
          
          		// resize all the adjacent panes, and adjust their toggler buttons
          		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
          		sizeHandles();
          		sizeContent(pane);
          		execUserCallback(pane, o.onresize_end || o.onresize);
          	};
          
          	/**
          	 * sizeMidPanes
          	 *
          	 * @callers  create(), open(), close(), onWindowResize()
          	 */
          	var sizeMidPanes = function (panes, overrideDims, onInit) {
          		if (!panes || panes == "all") panes = "east,west,center";
          
          		var d = getPaneDims();
          		if (overrideDims) $.extend( d, overrideDims );
          
          		$.each(panes.split(","), function() {
          			if (!$Ps[this]) return; // NO PANE - skip
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	hasRoom	= true
          			,	CSS		= {}
          			;
          
          			if (pane == "center") {
          				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
          				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
          				CSS.width  = max(1, cssW(pane, CSS.width));
          				CSS.height = max(1, cssH(pane, CSS.height));
          				hasRoom = (CSS.width > 1 && CSS.height > 1);
          				/*
          				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
          				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
          				 */
          				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
          					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
          					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
          				}
          			}
          			else { // for east and west, set only the height
          				CSS.top = d.top;
          				CSS.bottom = d.bottom;
          				CSS.height = max(1, cssH(pane, d.height));
          				hasRoom = (CSS.height > 1);
          			}
          
          			if (hasRoom) {
          				$P.css(CSS);
          				if (s.noRoom) {
          					s.noRoom = false;
          					if (s.isHidden) return;
          					else show(pane, !s.isClosed);
          					/* OLD CODE - keep until sure line above works right!
          					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
          					if ($R) $R.show();
          					*/
          				}
          				if (!onInit) {
          					sizeContent(pane);
          					execUserCallback(pane, o.onresize_end || o.onresize);
          				}
          			}
          			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
          				s.noRoom = true; // update state
          				if (s.isHidden) return;
          				if (onInit) { // skip onhide callback and other logic onLoad
          					$P.hide();
          					if ($R) $R.hide();
          				}
          				else hide(pane);
          			}
          		});
          	};
          
          
          	var sizeContent = function (panes) {
          		if (!panes || panes == "all") panes = c.allPanes;
          
          		$.each(panes.split(","), function() {
          			if (!$Cs[this]) return; // NO CONTENT - skip
          			var 
          				pane	= str(this)
          			,	ignore	= options[pane].contentIgnoreSelector
          			,	$P		= $Ps[pane]
          			,	$C		= $Cs[pane]
          			,	e_C		= $C[0]		// DOM element
          			,	height	= cssH($P);	// init to pane.innerHeight
          			;
          			$P.children().each(function() {
          				if (this == e_C) return; // Content elem - skip
          				var $E = $(this);
          				if (!ignore || !$E.is(ignore))
          					height -= $E.outerHeight();
          			});
          			if (height > 0)
          				height = cssH($C, height);
          			if (height < 1)
          				$C.hide(); // no room for content!
          			else
          				$C.css({ height: height }).show();
          		});
          	};
          
          
          	/**
          	 * sizeHandles
          	 *
          	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
          	 *
          	 * @callers  initHandles(), open(), close(), resizeAll()
          	 */
          	var sizeHandles = function (panes, onInit) {
          		if (!panes || panes == "all") panes = c.borderPanes;
          
          		$.each(panes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	$T		= $Ts[pane]
          			;
          			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
          
          			var 
          				dir			= c[pane].dir
          			,	_state		= (s.isClosed ? "_closed" : "_open")
          			,	spacing		= o["spacing"+ _state]
          			,	togAlign	= o["togglerAlign"+ _state]
          			,	togLen		= o["togglerLength"+ _state]
          			,	paneLen
          			,	offset
          			,	CSS = {}
          			;
          			if (spacing == 0) {
          				$R.hide();
          				return;
          			}
          			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
          				$R.show(); // in case was previously hidden
          
          			// Resizer Bar is ALWAYS same width/height of pane it is attached to
          			if (dir == "horz") { // north/south
          				paneLen = $P.outerWidth();
          				$R.css({
          					width:	max(1, cssW($R, paneLen)) // account for borders & padding
          				,	height:	max(1, cssH($R, spacing)) // ditto
          				,	left:	cssNum($P, "left")
          				});
          			}
          			else { // east/west
          				paneLen = $P.outerHeight();
          				$R.css({
          					height:	max(1, cssH($R, paneLen)) // account for borders & padding
          				,	width:	max(1, cssW($R, spacing)) // ditto
          				,	top:	cDims.top + getPaneSize("north", true)
          				//,	top:	cssNum($Ps["center"], "top")
          				});
          				
          			}
          
          			if ($T) {
          				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
          					$T.hide(); // always HIDE the toggler when 'sliding'
          					return;
          				}
          				else
          					$T.show(); // in case was previously hidden
          
          				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
          					togLen = paneLen;
          					offset = 0;
          				}
          				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
          					if (typeof togAlign == "string") {
          						switch (togAlign) {
          							case "top":
          							case "left":	offset = 0;
          											break;
          							case "bottom":
          							case "right":	offset = paneLen - togLen;
          											break;
          							case "middle":
          							case "center":
          							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
          						}
          					}
          					else { // togAlign = number
          						var x = parseInt(togAlign); //
          						if (togAlign >= 0) offset = x;
          						else offset = paneLen - togLen + x; // NOTE: x is negative!
          					}
          				}
          
          				var
          					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
          				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
          				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
          				;
          				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
          				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
          
          				if (dir == "horz") { // north/south
          					var width = cssW($T, togLen);
          					$T.css({
          						width:	max(0, width)  // account for borders & padding
          					,	height:	max(1, cssH($T, spacing)) // ditto
          					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
          				}
          				else { // east/west
          					var height = cssH($T, togLen);
          					$T.css({
          						height:	max(0, height)  // account for borders & padding
          					,	width:	max(1, cssW($T, spacing)) // ditto
          					,	top:	offset // POSITION the toggler
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
          				}
          
          
          			}
          
          			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
          			if (onInit && o.initHidden) {
          				$R.hide();
          				if ($T) $T.hide();
          			}
          		});
          	};
          
          
          	/**
          	 * resizeAll
          	 *
          	 * @callers  window.onresize(), callbacks or custom code
          	 */
          	var resizeAll = function () {
          		var
          			oldW	= cDims.innerWidth
          		,	oldH	= cDims.innerHeight
          		;
          		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
          
          		var
          			checkH	= (cDims.innerHeight < oldH)
          		,	checkW	= (cDims.innerWidth < oldW)
          		,	s, dir
          		;
          
          		if (checkH || checkW)
          			// NOTE special order for sizing: S-N-E-W
          			$.each(["south","north","east","west"], function(i,pane) {
          				s = state[pane];
          				dir = c[pane].dir;
          				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
          					setPaneMinMaxSizes(pane); // update pane-state
          					// shrink pane if 'too big' to fit
          					if (s.size > s.maxSize)
          						sizePane(pane, s.maxSize);
          				}
          			});
          
          		sizeMidPanes("all");
          		sizeHandles("all"); // reposition the toggler elements
          	};
          
          
          	/**
          	 * keyDown
          	 *
          	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
          	 *
          	 * @callers  document.keydown()
          	 */
          	function keyDown (evt) {
          		if (!evt) return true;
          		var code = evt.keyCode;
          		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
          
          		var
          			PANE = {
          				38: "north" // Up Cursor
          			,	40: "south" // Down Cursor
          			,	37: "west"  // Left Cursor
          			,	39: "east"  // Right Cursor
          			}
          		,	isCursorKey = (code >= 37 && code <= 40)
          		,	ALT = evt.altKey // no worky!
          		,	SHIFT = evt.shiftKey
          		,	CTRL = evt.ctrlKey
          		,	pane = false
          		,	s, o, k, m, el
          		;
          
          		if (!CTRL && !SHIFT)
          			return true; // no modifier key - abort
          		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
          			pane = PANE[code];
          		else // check to see if this matches a custom-hotkey
          			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
          				o = options[p];
          				k = o.customHotkey;
          				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
          				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
          					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
          						pane = p;
          						return false; // BREAK
          					}
          				}
          			});
          
          		if (!pane) return true; // no hotkey - abort
          
          		// validate pane
          		o = options[pane]; // get pane options
          		s = state[pane]; // get pane options
          		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
          
          		// see if user is in a 'form field' because may be 'selecting text'!
          		el = evt.target || evt.srcElement;
          		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
          			return true; // allow text-selection
          
          		// SYNTAX NOTES
          		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
          		// use "return false" to abort keystroke AND abort function
          		toggle(pane);
          		evt.stopPropagation();
          		evt.returnValue = false; // CANCEL key
          		return false;
          	};
          
          
          /*
           * ###########################
           *     UTILITY METHODS
           *   called externally only
           * ###########################
           */
          
          	function allowOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).attr("pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		;
          
          		// if pane is already raised, then reset it before doing it again!
          		// this would happen if allowOverflow is attached to BOTH the pane and an element 
          		if (s.cssSaved)
          			resetOverflow(pane); // reset previous CSS before continuing
          
          		// if pane is raised by sliding or resizing, or it's closed, then abort
          		if (s.isSliding || s.isResizing || s.isClosed) {
          			s.cssSaved = false;
          			return;
          		}
          
          		var
          			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
          		,	curCSS	= {}
          		,	of		= $P.css("overflow")
          		,	ofX		= $P.css("overflowX")
          		,	ofY		= $P.css("overflowY")
          		;
          		// determine which, if any, overflow settings need to be changed
          		if (of != "visible") {
          			curCSS.overflow = of;
          			newCSS.overflow = "visible";
          		}
          		if (ofX && ofX != "visible" && ofX != "auto") {
          			curCSS.overflowX = ofX;
          			newCSS.overflowX = "visible";
          		}
          		if (ofY && ofY != "visible" && ofY != "auto") {
          			curCSS.overflowY = ofX;
          			newCSS.overflowY = "visible";
          		}
          
          		// save the current overflow settings - even if blank!
          		s.cssSaved = curCSS;
          
          		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
          		$P.css( newCSS );
          
          		// make sure the zIndex of all other panes is normal
          		$.each(c.allPanes.split(","), function(i, p) {
          			if (p != pane) resetOverflow(p);
          		});
          
          	};
          
          	function resetOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		,	CSS		= s.cssSaved || {}
          		;
          		// reset the zIndex
          		if (!s.isSliding && !s.isResizing)
          			$P.css("zIndex", c.zIndex.pane_normal);
          
          		// reset Overflow - if necessary
          		$P.css( CSS );
          
          		// clear var
          		s.cssSaved = false;
          	};
          
          
          	/**
          	* getBtn
          	*
          	* Helper function to validate params received by addButton utilities
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
          	*/
          	function getBtn(selector, pane, action) {
          		var
          			$E = $(selector)
          		,	err = "Error Adding Button \n\nInvalid "
          		;
          		if (!$E.length) // element not found
          			alert(err+"selector: "+ selector);
          		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
          			alert(err+"pane: "+ pane);
          		else { // VALID
          			var btn = options[pane].buttonClass +"-"+ action;
          			$E.addClass( btn +" "+ btn +"-"+ pane );
          			return $E;
          		}
          		return false;  // INVALID
          	};
          
          
          	/**
          	* addToggleBtn
          	*
          	* Add a custom Toggler button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addToggleBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "toggle");
          		if ($E)
          			$E
          				.attr("title", state[pane].isClosed ? "Open" : "Close")
          				.click(function (evt) {
          					toggle(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addOpenBtn
          	*
          	* Add a custom Open button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addOpenBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "open");
          		if ($E)
          			$E
          				.attr("title", "Open")
          				.click(function (evt) {
          					open(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addCloseBtn
          	*
          	* Add a custom Close button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addCloseBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "close");
          		if ($E)
          			$E
          				.attr("title", "Close")
          				.click(function (evt) {
          					close(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addPinBtn
          	*
          	* Add a custom Pin button for a pane
          	*
          	* Four classes are added to the element, based on the paneClass for the associated pane...
          	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
          	*  - ui-layout-pane-pin
          	*  - ui-layout-pane-west-pin
          	*  - ui-layout-pane-pin-up
          	*  - ui-layout-pane-west-pin-up
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
          	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
          	*/
          	function addPinBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "pin");
          		if ($E) {
          			var s = state[pane];
          			$E.click(function (evt) {
          				setPinState($(this), pane, (s.isSliding || s.isClosed));
          				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
          				else close( pane ); // slide-closed
          				evt.stopPropagation();
          			});
          			// add up/down pin attributes and classes
          			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
          			// add this pin to the pane data so we can 'sync it' automatically
          			// PANE.pins key is an array so we can store multiple pins for each pane
          			c[pane].pins.push( selector ); // just save the selector string
          		}
          	};
          
          	/**
          	* syncPinBtns
          	*
          	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
          	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
          	*
          	* @callers  open(), close()
          	* @params  pane   These are the params returned to callbacks by layout()
          	* @params  doPin  True means set the pin 'down', False means 'up'
          	*/
          	function syncPinBtns (pane, doPin) {
          		$.each(c[pane].pins, function (i, selector) {
          			setPinState($(selector), pane, doPin);
          		});
          	};
          
          	/**
          	* setPinState
          	*
          	* Change the class of the pin button to make it look 'up' or 'down'
          	*
          	* @callers  addPinBtn(), syncPinBtns()
          	* @param Element  $Pin		The pin-span element in a jQuery wrapper
          	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
          	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
          	*/
          	function setPinState ($Pin, pane, doPin) {
          		var updown = $Pin.attr("pin");
          		if (updown && doPin == (updown=="down")) return; // already in correct state
          		var
          			root	= options[pane].buttonClass
          		,	class1	= root +"-pin"
          		,	class2	= class1 +"-"+ pane
          		,	UP1		= class1 + "-up"
          		,	UP2		= class2 + "-up"
          		,	DN1		= class1 + "-down"
          		,	DN2		= class2 + "-down"
          		;
          		$Pin
          			.attr("pin", doPin ? "down" : "up") // logic
          			.attr("title", doPin ? "Un-Pin" : "Pin")
          			.removeClass( doPin ? UP1 : DN1 ) 
          			.removeClass( doPin ? UP2 : DN2 ) 
          			.addClass( doPin ? DN1 : UP1 ) 
          			.addClass( doPin ? DN2 : UP2 ) 
          		;
          	};
          
          
          /*
           * ###########################
           * CREATE/RETURN BORDER-LAYOUT
           * ###########################
           */
          
          	// init global vars
          	var 
          		$Container = $(this).css({ overflow: "hidden" }) // Container elem
          	,	$Ps		= {} // Panes x4	- set in initPanes()
          	,	$Cs		= {} // Content x4	- set in initPanes()
          	,	$Rs		= {} // Resizers x4	- set in initHandles()
          	,	$Ts		= {} // Togglers x4	- set in initHandles()
          	//	object aliases
          	,	c		= config // alias for config hash
          	,	cDims	= state.container // alias for easy access to 'container dimensions'
          	;
          
          	// create the border layout NOW
          	create();
          
          	// return object pointers to expose data & option Properties, and primary action Methods
          	return {
          		options:		options			// property - options hash
          	,	state:			state			// property - dimensions hash
          	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
          	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
          	,	open:			open			// method - ditto
          	,	close:			close			// method - ditto
          	,	hide:			hide			// method - ditto
          	,	show:			show			// method - ditto
          	,	resizeContent:	sizeContent		// method - ditto
          	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
          	,	resizeAll:		resizeAll		// method - no parameters
          	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
          	,	addOpenBtn:		addOpenBtn		// utility - ditto
          	,	addCloseBtn:	addCloseBtn		// utility - ditto
          	,	addPinBtn:		addPinBtn		// utility - ditto
          	,	allowOverflow:	allowOverflow	// utility - pass calling element
          	,	resetOverflow:	resetOverflow	// utility - ditto
          	,	cssWidth:		cssW
          	,	cssHeight:		cssH
          	};
          
          }
          })( jQuery );
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        26. GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (369 bytes)
          GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 25809
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"25809-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (25809 bytes)
          /**
           * Version: 1.0 Alpha-1 
           * Build Date: 13-Nov-2007
           * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
           * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
           * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
           */
          Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
          Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
          return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
          if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
          var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
          if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
          if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
          if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
          if(x.month||x.months){this.addMonths(x.month||x.months);}
          if(x.year||x.years){this.addYears(x.year||x.years);}
          if(x.day||x.days){this.addDays(x.day||x.days);}
          return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
          return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
          if(!x.second&&x.second!==0){x.second=-1;}
          if(!x.minute&&x.minute!==0){x.minute=-1;}
          if(!x.hour&&x.hour!==0){x.hour=-1;}
          if(!x.day&&x.day!==0){x.day=-1;}
          if(!x.month&&x.month!==0){x.month=-1;}
          if(!x.year&&x.year!==0){x.year=-1;}
          if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
          if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
          if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
          if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
          if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
          if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
          if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
          if(x.timezone){this.setTimezone(x.timezone);}
          if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
          return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
          var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
          return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
          Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
          return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
          var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
          return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
          var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
          return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
          (function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
          break;}
          return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
          return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
          throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
          return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
          if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){r=null;}
          if(r){return r;}}
          throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
          return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
          rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
          s=q[1];}
          if(!r){throw new $P.Exception(s);}
          if(q){throw new $P.Exception(q[1]);}
          if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
          return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
          rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
          if(!last&&q[1].length===0){last=true;}
          if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
          p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
          if(rx[1].length<best[1].length){best=rx;}
          if(best[1].length===0){break;}}
          if(best[0].length===0){return best;}
          if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
          best[1]=q[1];}
          return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
          return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
          if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
          var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
          return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
          this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
          var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
          return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
          for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
          if(this.now){return new Date();}
          var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
          if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
          if(!this.unit){this.unit="day";}
          if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
          if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
          this[this.unit+"s"]=this.value*orient;}
          return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
          if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
          if(this.month&&!this.day){this.day=1;}
          return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
          fn=_C[keys]=_.any.apply(null,px);}
          return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
          return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
          return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
          try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        27. GET https://dev.duracloud.org/duradmin/spaces
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (354 bytes)
          GET https://dev.duracloud.org/duradmin/spaces HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (630 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        28. GET https://dev.duracloud.org/duradmin/style/base.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (362 bytes)
          GET https://dev.duracloud.org/duradmin/style/base.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (437 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 21115
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"21115-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (21115 bytes)
          /*
          * Created by Daniel Bernstein
          * Modified by Charles Hacskaylo
          */
          
          /* RESETTERS *************************************************/
          /* Eric Meyer:
          /* v1.0 | 20080212 */
          
          html, body, div, span, applet, object, iframe,
          h1, h2, h3, h4, h5, h6, p, blockquote, pre,
          a, abbr, acronym, address, big, button, cite, code,
          del, dfn, em, font, img, ins, kbd, q, s, samp,
          small, strike, strong, sub, sup, tt, var,
          b, u, i, center,
          dl, dt, dd, ol, ul, li,
          fieldset, form, label, legend,
          table, caption, tbody, tfoot, thead, tr, th, td {
          	margin: 0;
          	padding: 0;
          	border: 0;
          	outline: 0;
          	font-size: 100%;
          	vertical-align: baseline;
          	background: transparent;
          }
          body {
          	line-height: 1;
          }
          
          a:hover {
            cursor:pointer;
          }
          
          ol, ul {
          	list-style: none;
          }
          
          
          ul.bullets,
          #static-panel ul
          {
          	line-height:130%;
          	list-style:square;
          	margin-left:15px;
          }
          
          blockquote, q {
          	quotes: none;
          }
          blockquote:before, blockquote:after,
          q:before, q:after {
          	content: '';
          	content: none;
          }
          
          /* remember to define focus styles! */
          :focus {
          	outline: 0;
          }
          
          /* tables still need 'cellspacing="0"' in the markup */
          table {
          	border-collapse: collapse;
          	border-spacing: 0;
          }
          
          /* set input color for autofill */
          input:-webkit-autofill {
              color: #000 !important;
          }
          
          
          
          
          
          
          /* CLEARFIX *************************************************/
          
          .clearfix:after {
               visibility: hidden;
               display: block;
               font-size: 0;
               content: " ";
               clear: both;
               height: 0;
               }
          .clearfix { display: inline-block; }
          /* start commented backslash hack \*/
          * html .clearfix { height: 1%; }
          .clearfix { display: block; }
          /* close commented backslash hack */
          
          
          .horizontal-list li
          {
          	display:inline-block;
          }
          
          
          body {
          	background:#fff url(../images/bg_clouds.jpg) repeat-y;
          	font-family: Verdana, Helvetica, sans-serif;
          	font-size:1em;
          	*font-size:	90%; /* IE only */
          	margin-right:10px !important;
          }
          
          h1, h2, h3
          {
          	font-family:Helvetica, Sans-Serif;
          }
          
          h1 { font-size:2em; font-weight:normal; }
          h2 { font-size:1.3em; font-weight:normal; }
          h3 { font-size:1em; }
          
          
          .float-l {float:left; margin-left:0; }
          .float-r {float:right; margin-right:0; }
          .content-centered { text-align:center !important; }
          
          
          /* MAIN PAGE ELEMENTS ******************************************/
          
          body > #page-header
          {
          	height:87px;
          	min-width:960px;
          	padding-top:10px;
          }
          
          .pane-L1-body
          {
          	background:url(../images/bg_L1.png) no-repeat top right;
          	padding-top:5px;
          }
          
          .pane-L1-body a
          {
          	color:#ccc;
          }
          
          .center-pane-north
          {
          	color:#9b9b9b;
          	font-size:13px;
          	padding:5px 10px;
          	z-index:4 !important; /* needed to list spaces provider menu above elements below it */
          }
          
          .dc-prototype {
          
          	display:none;
          }
          
          .list-browser
          {
          	background:#4F4F4F no-repeat top right;
          }
          
          .ui-layout-pane-west
          {
          	font-size:11px;
          }
          
          .dc-item-list-filter
          {
          	background-color:#4F4F4F;
          	border:1px solid #999;
          	color:#ccc;
          	font-style:italic;
          	padding:2px;
          	width:143px;
          	float: right;
          }
          
          .dc-item-list-wrapper
          {
          	background-color:#cbcbcb;
          	border:1px solid #595959;
          	border-top-color:#333;
          	border-bottom-color:#4F4F4F;
          	color:#000;
          	min-width:250px !important;
          	overflow:auto;
          	width:auto !important;
          }
          
          .dc-item-list-wrapper a
          {
          	color:#000;
          }
          
          .dc-selectablelist-footer {
          	padding-right:10px;
          }
          
          .dc-link:hover {
          	text-decoration:underline;
          	cursor: pointer;
          }
          
          .dc-link:after {
          	content:'>';
          }
          
          .dc-selectablelist-hl {
          	background:#DDDDDD;
          }
          
          
          .list-header
          {
          	padding:5px 5px 5px 10px;
          }
          
          .header-section
          {
          	min-width:250px !important;
          	padding-bottom:3px;
          	white-space:nowrap;
          }
          
          .list-header h2
          {
          	display:inline-block;
          	font-size:16px;
          	line-height:24px;
          }
          
          #spaces-list-view .list-header .button span,
          #content-item-list-view .list-header .button span
          {
          	width:130px;
          }
          
          #space-filter {
              width: 100px;
          }
          
          .item-scroll-action:hover {
          	color:#EEE;
          	font-weight:bold;
          }
          
          .item-scroll-action{
          	text-decoration: none;
          }
          
          .ui-layout-pane
          {
          	color:#fff;
          }
          
          #provider-logo
          {
              float:left;
              margin-left:0;
              height:39px;
          	width:184px;
          }
          
          .amazon_s3-logo
          {
              background:url(../images/amazon.png) no-repeat;
          }
          
          .amazon_glacier-logo
          {
              background:url(../images/amazon.png) no-repeat;
          }
          
          .chronopolis-logo
          {
          	background:url(../images/chronopolis.png) no-repeat;
          }
          
          .swift_s3-logo
          {
              background:url(../images/swift.png) no-repeat;
          }
          
          .ui-layout-resizer
          {
          	background-color:#4b4b4b;
          	cursor:col-resize !important;
          }
          
          .ui-layout-resizer:hover
          {
          	background-color:#257bba !important;
          	cursor:col-resize !important;
          	opacity:1 !important;
          }
          
          #spaces-list-view-resizer
          {
          	background-color:#4F4F4F;
          }
          
          #list-browser-resizer
          {
          
          }
          
          ul.dc-user-config > li:first-child, .dc-exclusion-group > ul > li {
          	border-top:0px;
          }
          
          ul.dc-user-config > li:last-child {
          	border-bottom: 0px;
          }
          
          
          .dc-exclusion-group  li {
          	margin-left: 30px;
          	border-bottom: 0px;
          	border-top: 0px;
          }
          
          .dc-exclusion-group  ul {
          	margin-left:30px;
          	border-left:1px solid #555555;
          	background: #666666 !important;
          	padding-left:10px;
          }
          
          .dc-exclusion-group > ul > li > label {
          	width:250px !important;
          	margin-right:10px;
          }
          
          .dc-exclusion-group > ul > li {
          	border-bottom: 1px solid #777777;
          }
          
          .dc-exclusion-group > label, .dc-exclusion-group > select
          {
          	margin-bottom: 10px;
          }
          
          .dc-exclusion-group  li:last-child {
          	border-bottom: 0px;
          }
          
          
          .ui-layout-toggler
          {
          	background:url(../images/grippy.gif) no-repeat left top;
          	height:100px !important;
          }
          
          .footer
          {
          	background:url(../images/bg_L1_btm.png) no-repeat right -8px;
          	height:70px !important;
          	padding:0px 10px;
          }
          
          .footer #status-holder
          {
          	color:#ccc;
          	font-size:11px;
          	height:27px;
          	padding-top:2px;
          	text-align:right;
          }
          
          .footer #status-holder a { color:#ccc; text-decoration:none; }
          .footer #status-holder a:hover { color:#fff; }
          
          #status-holder #progress-bar
          {
          	background:url("/duradmin/images/loading-bar-green.gif") no-repeat left 2px;
          	display:inline-block;
          	height:20px;
          	width:110px;
          	vertical-align:middle;
          
          }
          
          #status-holder {
          }
          
          #footer-content { margin-top:15px; }
          
          #footer-content #logo-ds
          {
          	background:url(../images/logo_lyrasis.png) no-repeat top left;
          	margin-top:-5px;
          	width:116px;
          	height:18px;
          }
          
          .footer .sep
          {
          	color:#272727;
          }
          
          .hint
          {
          	font-size:11px;
          }
          
          /* TABS **********************************************/
          /* Extends css.flex *****/
          
          .dc-main-tabs
          {
          	position:absolute;
          	left:10px;
          	top:65px;
          	opacity:0.7;
          }
          
          .dc-main-tabs li
          {
          	margin:0;
          }
          
          .dc-main-tabs a,
          .dc-main-tabs a span
          {
          	color:#000;
          	font-size:13px;
          	height:22px;
          	line-height:22px;
          }
          
          .dc-main-tabs a span
          {
          	margin:0 -2px;
          	padding-left:2px;
          	font-weight:bold;
          }
          
          .dc-main-tabs .selected a,
          .dc-main-tabs a:hover
          {
          	background:url(../images/tab.gif) no-repeat top left;
          }
          
          .dc-main-tabs .selected a span,
          .dc-main-tabs a:hover span
          {
          	background:url(../images/tab.gif) no-repeat top right;
          	color:#fff !important;
          }
          
          /* LIST AND ITEMS **********************************************/
          
          .dc-item-list
          {
          	margin:5px;
          }
          
          .dc-item-list table
          {
          	width:100%;
          }
          
          .dc-item,
          .dc-item td,
          .dc-item-list th
          {
          	border-bottom:1px solid #bbbbbb;
          	border-collapse:  collapse;
          	color:#000;
          	padding-bottom:2px;
          	padding-top:2px;
          	text-align:left;
          	vertical-align:middle;
          }
          
          .dc-item {
              position:relative;
          	min-height:20px;
          }
          .dc-item-list td,
          .dc-item-list th
          {
          	padding:3px 5px;
          }
          
          .dc-item-list td.icon
          {
          	width:38px;
          }
          
          .dc-item-list th
          {
          	background-color:#aaa;
          	border-left:1px solid #ccc;
          }
          
          .dc-item-list td.icon div
          {
          	/* graphics format: art is 32 x 32, horizontal, with 10px between each, so total offset from icon to icon is 42px */
          	background:url(../images/icons_services.png) no-repeat;
          	width:32px;
          	height:32px;
          }
          
          /* replicate 0; general-compute -42; bit-integrity -84; image -126; video -168; file-transform -210; */
          
          .dc-item-list .service-replicate td.icon div { background-position:0 0; }
          .dc-item-list .service-generalcompute td.icon div { background-position:-42px 0; }
          .dc-item-list .service-bitintegrity td.icon div { background-position:-84px 0; }
          .dc-item-list .service-image td.icon div { background-position:-126px 0; }
          .dc-item-list .service-video td.icon div { background-position:-168px 0; }
          .dc-item-list .service-filetransform td.icon div { background-position:-210px 0; }
          
          /* bitintegrity */
          .dc-item-list .service-0 td.icon div { background-position:-84px 0; }
          .dc-item-list .service-1 td.icon div { background-position:-84px 0; }
          .dc-item-list .service-2 td.icon div { background-position:-84px 0; }
          
          /* image */
          .dc-item-list .service-5 td.icon div { background-position:-126px 0; }
          .dc-item-list .service-6 td.icon div { background-position:-126px 0; }
          .dc-item-list .service-7 td.icon div { background-position:-126px 0; }
          
          /* filetransform */
          .dc-item-list .service-8 td.icon div { background-position:-210px 0; }
          
          .dc-selected-list-item {
          	background-color:#7e7e7e;
          }
          
          input.dc-check-all
          {
          	margin-left:3px !important;
          }
          
          .dc-checked-selected-list-item {
          	background-color:#888;
          	color:#FFF;
          }
          
          .dc-checked-list-item {
          	background-color:#999;
          	color:#FFF;
          }
          
          .dc-item div:first-child {
          	/*
          
          	float:left;*/
          }
          
          .dc-item-list .dc-action-panel{
              position:absolute;
              right:0;
              top:4px;
          }
          
          .dc-action-panel
          {
          	/*margin-right:20px;*/
          }
          
          .dc-item-content {
              padding-right: 30px;
          }
          
          .dc-item .cb-holder{
          	padding:8px 8px 8px 5px;
          }
          
          .dc-item:hover,
          .dc-item:hover td
          {
          	background-color:#9b9b9b;
          	cursor: pointer;
          }
          
          /* PAGE TOP ********************************************************/
          
          #dc-logo-panel
          {
          	padding-left:10px;
          }
          
          #dc-logo,
          #dc-app-title
          {
          	background-repeat:no-repeat;
          	display:inline-block;
          	float:left;
          	height:45px;
          }
          
          #dc-logo
          {
          	background-image:url(../images/logo_top_duracloud.png);
          	width:110px;
          	color: transparent;
          }
          
          #page-header #dc-app-title
          {
          	width:280px;
          }
          
          #page-header #dc-user
          {
          	border-right:solid 1px #ccc;
          	height:60px;
          	margin-right:10px;
          	padding-right:20px;
          	text-align:right;
          	width:400px;
          }
          
          .outer,
          .outer a
          {
          	color:#2c2c2c;
          	font-size:14px;
          }
          
          .outer .icon-link:hover
          {
          	color:#000;
          }
          
          
          .dc-mouse-panel {
          	visibility: hidden;
          }
          
          .dc-mouse-panel-activator
          {
          	cursor:pointer;
          }
          
          .dc-toggler {
          	float:right;
          	background: url(../images/icon_sm_arw_blue_updown.gif) no-repeat right top;
          	width:11px;
          	height:25px;
          }
          
          .dc-toggler-close { background-position:left top; }
          
          
          .dc-expandable-panel div:first-child{
          	cursor: pointer;
          }
          
          /* DETAIL PANE ****************************************************/
          
          .detail-pane
          {
          	padding-right:5px !important;
          }
          
          .detail-pane h1
          {
          	color:#777;
          	margin-bottom:10px;
          }
          
          .detail-pane > .north {
          	overflow: auto;
          	overflow-x: auto;
          }
          
          .detail-pane th {
          	text-align: left;
          	background-color: #555;
          	padding: 5px 0px 5px 0px;
          }
          
          h2,.footer-prompt
          {
              color:#F0F0F0;
          }
          
          .footer-prompt {
            font-size: smaller;
          }
          
          .detail-pane h3
          {
          	color:#fff;
          	margin-bottom:10px;
          }
          
          .detail-pane .north
          {
          	background:url(../images/bg_details_header.png) repeat-x bottom left;
          	padding:0 10px;
          	position:relative;
          }
          
          .detail-pane .center
          {
          	background-color:#414141;
          	border:1px solid #2d2d2d;
          	border-top-color:#333;
          	border-bottom-color:#999;
          	font-family:Verdana, Sans-Serif;
          	font-size:11px;
          	overflow-x:hidden;
          	overflow-y:scroll;
          }
          
          .detail-pane .center {
          	width:auto !important;
          }
          
          .detail-pane .segment-header,
          #add-remove-properties-dialog .segment-header
          {
          	background:url(../images/bg_segment_header.gif) repeat-x top left;
          	border-bottom:1px solid #333;
          	color:#DBDBDB;
          	cursor:pointer;
          	font-size:13px;
          	height:28px;
          	line-height:25px;
          	padding:0 10px;
          }
          
          .detail-pane .segment-header:hover,
          #add-remove-properties-dialog .segment-header:hover
          {
          	color:#fff;
          }
          
          .detail-pane .segment-content,
          #add-remove-properties-dialog .segment-content
          {
          	padding:10px;
          }
          
          .detail-pane .segment-content table,
          #add-remove-properties-dialog .segment-content table
          {
          	width:100%;
          }
          
          .detail-pane .segment-content table td,
          #add-remove-properties-dialog .segment-content table td
          {
          	border-bottom:1px solid #555;
          	padding:4px 5px 4px 0;
          }
          
          .detail-pane .segment-content table td.label,
          span.label,
          #add-remove-properties-dialog .segment-content table td.label
          {
          	color:#999;
          }
          
          .detail-pane .segment-content table td.label,
          #add-remove-properties-dialog .segment-content table td.label
          {
          	width:30%;
          }
          
          
          .detail-pane .segment-content table td.value,
          #add-remove-properties-dialog .segment-content table td.value
          {
          	width:70%;
          }
          
          .detail-pane .segment-content input,
          #add-remove-properties-dialog .segment-content input
          {
          	background-color:#484747;
          	border:1px solid #727576;
          	color:#ccc;
          	padding:2px;
          }
          
          .segment-content h4 {
          	margin: 10px 0px 5px 0px;
          	padding: 10px 5px 10px 5px;
          	height: 25px;
          	border-top: 1px solid #555;
          }
          
          .segment-content h4 span {
          	margin-top: 5px;
          }
          .segment-content h4 button {
          	float:right;
          }
          
          
          .detail-pane .mime-type
          {
          	font-size:13px;
          	height:40px;
          	line-height:40px;
          	margin:10px 0;
          }
          
          .mime-type-image-holder
          {
          	background:url(../images/icons_mimetypes.png) no-repeat;
          	background-position:-40px 0;
          	height:40px;
          	width:40px;
          }
          
          .detail-pane .mime-type-image-holder
          {
          	margin-right:10px;
          }
          
          .mime-type-application { background-position:-80px 0 !important; }
          .mime-type-audio { background-position:-240px 0 !important; }
          .mime-type-compression { background-position:-480px 0 !important; }
          .mime-type-drawing { background-position:-200px 0 !important; }
          .mime-type-generic { background-position:0 0 !important; }
          .mime-type-globe { background-position:-160px 0 !important; }
          .mime-type-image { background-position:-200px 0 !important; }
          .mime-type-message { background-position:-280px 0 !important; }
          .mime-type-text { background-position:-320px 0 !important; }
          .mime-type-music { background-position:-360px 0 !important; }
          .mime-type-spreadsheet { background-position:-440px 0 !important; }
          .mime-type-unknown { background-position:-40px 0 !important; }
          .mime-type-xml { background-position:-520px 0 !important; }
          .mime-type-video { background-position:-120px 0 !important; }
          
          .preview-image-wrapper
          {
          	display:block;
          	margin:0 auto;
          	overflow:hidden;
          	text-align:center;
          	padding-top:10px;
          	padding-bottom:10px;
          	min-width:300px;
          	min-height:200px;
          }
          
          
          
           /* ERRORS *********************************************************/
          
           .error, .warning
           {
           	color:#ccc;
           	margin-bottom:10px;
           }
          
          .error,.failure
           {
           	border:1px solid #aa0000;
           	background-color:#990000;
           }
          .warning
           {
           	border:1px solid #ff9933;
          	background-color:#ff6600;
           }
          
           .success {
           	border:1px solid #00AA00;
          	background-color:#009900;
           }
          
           .info {
              background-color:#2e9acc;
           }
           .info, .success, .warning, .error {
          	border-radius: 5px;
          	padding:5px;
           }
          
          .detail-pane label.error {
          	padding:0px;
           }
          
           .health-check {
           	padding:5px;
           }
          
           /* MISC **********************************************************/
          
           .object-id {
           	display:none;
           }
          
           /*flyout select default styling ******************************************/
          
          .provider-widget
          {
          	display:inline-block;
          	position:relative;
          }
          
          .provider-widget ul
          {
          	-moz-border-radius:3px;
          	border-radius:3px;
          	-webkit-border-radius:3px;
          	background-color:#2886c0;
          	border:1px solid #257ab9;
          	border-bottom-color:#0c293f;
          	border-top-color:#2e9acc;
          	display:none;
          	padding:10px;
          	opacity:0.95;
          	position:absolute;
          	z-index:5000;
          }
          
          .provider-widget li
          {
          	border-top:1px solid #2e9acc;
          	white-space:nowrap;
          	min-width:100px;
          }
          
          .provider-widget li a
          {
          	color:#ffffff;
          	cursor:pointer;
          	display:block;
          	font-size:11px;
          	padding:6px 3px;
          	text-decoration:none;
          }
          
          .provider-widget li a:hover
          {
          	background-color:#2e9acc;
          	color:#fff;
          }
          
          /* doing this via jquery to support IE, so turned off here
          #select-provider-wrapper:hover ul
          {
          	display:block;
          }
          */
          
           .provider-widget li:first-child{
           	border-top:none !important;
           }
          
          .provider-widget > a,
          .provider-widget > a span
          {
          	background-image:url(../images/btn_provider.gif);
          
          }
          
          .provider-widget > a span i
          {
          	color:#76e8ff !important;
          	min-width:150px;
          }
          
          .provider-float
          {
              float: right;
          }
          
          .dc-expando-status {
          	height:20px;
          	width:30px;
          }
          
          .dc-busy {
          	background: url('../images/wait.gif') no-repeat center center;
          	display:inline-block; vertical-align:middle;
          	height:20px;
          	width:20px;
          }
          
          .dc-removing {
          	background-color: orange;
          	filter:alpha(opacity=0.25);
          	-moz-opacity:0.25;
          	-khtml-opacity: 0.25;
          	opacity: 0.25;
          }
          
          .dc-progressbar
          {
          	display:block;
          	background-color:#003300;
          	border:1px solid #000;
          	border-bottom-color:#454545;
          }
          
          .dc-progressbar .dc-progressbar-value
          {
          	background-color:#227722;
          	border:1px solid #228822;
          	border-top-color:#339933;
          	border-bottom-width:0;
          	color:#00cc00;
          	display:block;
          	overflow:visible;
          	padding:1px 0px 3px 0px;
          	text-align:left;
          	white-space:nowrap;
          }
          
          .dc-failure, .dc-progressbar .dc-failure {
          	background-color:#772222;
          	border:1px solid #882222;
          	border-top-color:#993333;
          	color:#cc0000;
          }
          
          .dc-cancelled, .dc-progress-bar .dc-cancelled {
          	background-color:#222277;
          	border:1px solid #222288;
          	border-top-color:#333399;
          	color:#0000cc;
          }
          
          
          .dc-progress-state {
          	padding-right:1em;
          }
          
          .dc-controls
          {
          	float:right;
          	color: white;
          }
          
          
          #busy-dialog-title {
          	margin-bottom:20px;
          }
          #busy-dialog-progressbar  {
          	height: 30px;
          	width: 100%;
          	background: url('../images/loading-bar-green.gif') no-repeat center center;
          }
          
          .ui-serviceconfig > div {
          	height: 420px;
          	overflow: auto;
          }
          
          
          p.ui-serviceconfig-no-config{
          	padding: 10px 0px 10px 0px;
          }
          
          /*
          * hiding the jquery-ui dialog title bars globally.
          */
          .ui-dialog-titlebar{
          	display:none;
          }
          
          
          .dc-graph {
          	width:300px;
          	height:150px;
          	padding:20px;
              margin-bottom:10px;
          }
          
          .dc-breadcrumb  li:after {
          	content:' :: '
          }
          
          
          .dc-breadcrumb li {
          	cursor: pointer;
          	font-size:0.9em;
          	color:#555
          }
          
          
          .dc-breadcrumb-title {
          	font-size:1.3em !important;
          	color:#555 !important;
          
          }
          
          
          .dc-breadcrumb ul{
          
          }
          
          .dc-report-panel {
          
          }
          
          .dc-hidden {
          	display:none;
          }
          .dc-date-slider > div {
          	 display:inline-block;
          }
          
          .number {
          	text-align:right;
          }
          
          
          
          
          table.tablesorter {
              background-color: #CDCDCD;
              font-family: arial;
              font-size: 8pt;
              margin: 10px 0 15px;
              text-align: left;
              width: 100%;
          }
          table.tablesorter thead tr th, table.tablesorter tfoot tr th {
              background-color: #E6EEEE;
              border: 1px solid #FFFFFF;
              font-size: 8pt;
              padding: 4px;
          }
          table.tablesorter thead tr .header {
              background-image: url("bg.gif");
              background-position: right center;
              background-repeat: no-repeat;
              cursor: pointer;
          }
          table.tablesorter tbody td {
              background-color: #FFFFFF;
              color: #3D3D3D;
              padding: 4px;
              vertical-align: top;
          }
          table.tablesorter tbody tr.odd td {
              background-color: #F0F0F6;
          }
          table.tablesorter thead tr .headerSortUp {
              background-image: url("../images/asc.gif");
          }
          table.tablesorter thead tr .headerSortDown {
              background-image: url("../images/desc.gif");
          }
          table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
              background-color: #8DBDD8;
          }
          
          table.tablesorter tr:nth-child(even) {
          	background-color: #DDDDDD;
          }
          
          table.tablesorter tr {
          	border-bottom: 1px solid #CCCCCC;
          }
          
          /*
          * Upload tool
          */
          
          .upload-tool {
          	padding:10px;
              position:relative;
          }
          
          .upload-tool-help {
              position:absolute;
              left:765px;
              font-size: 0.7em;
              margin-top: 4px;
          }
          
          .dc-controlpanel .dc-controlpanel-header > * {
          	float:right;
          }
          
          .dc-controlpanel .dc-controlpanel-header  {
          	background-color: #444;
          	padding: 5px;
          	height:25px;
          }
          
          .dc-controlpanel input[type="checkbox"]  {
          	margin:0px 5px 0px 5px !important;
          }
          
          table.dc-acls td:first-child {
          	width:50%;
          }
          
          table.dc-acls td:last-child {
          	width:25% ;
          }
          
          .user, .group {
          	padding-left:20px;
          }
          
          .dc-graph {
          	width:150px;
          	height:150px;
          	display:inline-block;
          }
          
          .dc-graph-holder {
          	display:inline-block;
          	text-align: center;
          }
          
          .dc-graph-holder {
          	margin-left: 40px;
          
          }
           .history-panel #summaries-graph {
           	height:150px;
          	display:inline-block;
          
           }
          
           .history-panel .segment-content > * {
              width: 95%;
           }
          
           .history-panel #summaries-legend {
          	display:block;
          	color: #EEE;
          	padding:5px;
           }
           .history-panel #summaries-legend table {
           	border: 1px solid #555;
           }
          
          .history-panel #summaries-legend .legendLabel{
          	color: #EEE;
          }
          
          .history-panel #summaries-legend table {
          	width: 50px !important;
          }
          
          .history-panel h6 {
          	margin-bottom: 10px;
          }
          
          #streaming-pane > p {
          	margin-bottom: 20px;
          }
          
          #hlsSwitchControl {
          	border-bottom: 1px solid #555;
          	padding-bottom:10px;
          	margin-bottom:10px;
          	width:100%;
          	display: inline-block;
          	margin-top: 20px;
          
          }
          
          #hlsSwitchControl {
          	margin-top: 25px;
          }
          
          .streaming-switch-holder {
          	height:20px;
          	display:inline-block;
          	white-space: nowrap;
          	margin-bottom: 20px;
          }
          .streaming-switch-holder label {
          	font-size: 1.25em;
          }
          
          .streaming-switch {
          	display:inline-block;
          	font-size:0.7em;
          }
          
          .button-bar {
          	white-space: nowrap;
          }
          
          .object-name {
          	white-space: nowrap;
          	margin-bottom: 10px !important;
          }
          
          button#enable-streaming {
          	margin-top:10px;
          }
          
          button.add-space-button {
            display: none;
          }
          
          .dc-item-divider {
            background-color:#5b5b5b;
            padding:5px;
            font-weight: bold;
          
          }
          
          .dc-busy-holder {
              background: url('../images/wait.gif') no-repeat left center;
              display:inline-block;
              vertical-align:middle;
              height:20px;
              width:20px;
              min-width:30px;
              font-size: 10px;
              padding-left:20px;
          }
          
          div.snapshot.dc-item {
            padding: 5px 5px 0px 7px;
          }
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        29. GET https://dev.duracloud.org/duradmin/style/buttons.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (365 bytes)
          GET https://dev.duracloud.org/duradmin/style/buttons.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 8525
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"8525-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (8525 bytes)
          /* css classes for buttons and a tags as buttons */
          
          button::-moz-focus-inner
          {
          	border: none;  /* overrides extra padding in Firefox */
          	padding:0 !important;
          }
          
          button a
          {
          	text-decoration:none;
          }
          
          button,
          .button,
          .icon-link,
          .switch-holder,
          .switch
          {
          	font-family:Verdana, Helvetica, Sans-Serif;
          	font-size:11px;
          	font-style:normal;
          	white-space:nowrap;
          	width:auto;
          }
          
          button,
          .button,
          .icon-link,
          .switch
          {
          	color:#ccc;
          	display:inline-block;
          	position:relative;
          	overflow: visible; /* removes extra side padding in IE */
          	text-align:center;
          	text-decoration:none;
          	vertical-align:middle;
          }
          
          button,
          .button,
          .switch
          {
          	-moz-border-radius:5px;	
          	-webkit-border-radius:5px;
          	border-radius:5px;
          	border-width:1px;
          	border-style:solid;
          	border-color:#333;
          	padding:1px 10px 0 10px;
          
          }
          
          button,
          .button
          {	
          	background-color:#313131;
          	background: -moz-linear-gradient(top, #595959, #313131);
          	background: -webkit-gradient(linear, left top, left bottom, from(#595959), to(#313131)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF595959, endColorstr=#FF313131); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF59595, endColorstr=#FF313131)";	/* For Internet Explorer 8 */
          	cursor:pointer;
          	height:25px;
          	margin-right:2px !important;
          
          }
          
          .button
          {
          	padding-top:4px;
          	height:19px;
          }
          
          button,
          a.button,
          button.featured,
          a.button.featured
          { 
          	background-color:#bbb !important;
          	background: -moz-linear-gradient(top, #e4e4e4, #999999);
          	background: -webkit-gradient(linear, left top, left bottom, from(#e4e4e4), to(#999999)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFe4e4e4, endColorstr=#FF999999); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFe4e4e4, endColorstr=#FF999999)";	/* For Internet Explorer 8 */
          	color:#444 !important;
          }
          
          button.primary,
          .button.primary
          {
          
          	background-color:#2375b2;
          	background: -moz-linear-gradient(top, #37a9de, #2375b2);
          	background: -webkit-gradient(linear, left top, left bottom, from(#37a9de), to(#2375b2)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF37a9de, endColorstr=#FF2375b2); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF37a9de, endColorstr=#FF2375b2)";	/* For Internet Explorer 8 */
          	color:#ffffff !important;
              width:122px;
          }
          
          button.primary:hover,
          a.button.primary:hover
          {
          
          	background-color:#3793d6;
          	background: -moz-linear-gradient(top, #4db6e8, #3793d6);
          	background: -webkit-gradient(linear, left top, left bottom, from(#4db6e8), to(#3793d6)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF4db6e8, endColorstr=#FF3793d6); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF4db6e8, endColorstr=#FF3793d6)";	/* For Internet Explorer 8 */
          	border-color:#4db6e8;
          	color:#ffffff;
          }
          
          button.small,
          .button.small
          {
          	height:20px;
          }
          
          
          button:hover,
          a.button:hover,
          button.featured:hover,
          a.button.featured:hover
          { 
          	background-color:#c9c9c9 !important;
          	background: -moz-linear-gradient(top, #f8f8f8, #c9c9c9);
          	background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#c9c9c9)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFf8f8f8, endColorstr=#FFc9c9c9); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFf8f8f8, endColorstr=#FFc9c9c9)";	/* For Internet Explorer 8 */
          	color:#000; 
          }
          
          
          button[disabled], button[disabled]:hover,
          .button[disabled], .button[disabled]:hover 
          
          {	
          	background-color:#515151 !important;
          	background: -moz-linear-gradient(top, #797979, #515151) !important;
          	background: -webkit-gradient(linear, left top, left bottom, from(#797979), to(#515151)) !important; 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF797979, endColorstr=#FF515151) !important; /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF797979, endColorstr=#FF515151)" !important;	/* For Internet Explorer 8 */
          	margin-right:2px;
          	color: #333 !important;
          	border-color:#333 !important;
          	cursor: default;
          	pointer-events: none;
          	
          }
          
          
          button i,
          span.switch i,
          .button i,
          .icon-link i
          {
          	background-position:0 0;
          	background-repeat:no-repeat;
          	display:inline-block;
          	height:16px;
          	margin-top:-1px;
          	vertical-align:middle;
          	width:14px;
          }
          
          .icon-link:hover i
          {
          	background-position:left 0;
          }
          
          span.switch i, .button i { margin-top:0; }
          
          button i.pre,
          .button i.pre,
          .icon-link i,
          span.switch i.pre
          {
          	margin-left:-3px;
          	margin-right:5px;
          }
          
          button i.post,
          .button i.post,
          span.switch i.post
          {
          	margin-left:3px;
          	margin-right:-5px;
          }
          
          .icon-only
          {
          	padding-right:5px;
          }
          
          .icon-only .pre {
              margin-right:0;
              color: transparent;
          }
          
          
          /* SWTICHES *****************************************************/
          
          .switch-holder
          {
          	background-color:#545454;
          	-moz-border-radius:8px;	
          	-webkit-border-radius:8px;
          	border-radius:8px;
          	margin:20px 0;
          	padding:7px;
          }
          
          .switch { margin:0 }
          
          span.switch
          {
          	box-shadow:inset 0 0 3px #000000;
             -moz-box-shadow:inset 0 0 3px #000000;
             -webkit-box-shadow:inset 0 0 3px #000000;
          	height:19px;
          	padding-top:4px;
          }
          
          .switch.left
          {
          	-webkit-border-top-right-radius: 0px;
          	-webkit-border-bottom-right-radius: 0px;
          	-moz-border-radius-topright: 0px;
          	-moz-border-radius-bottomright: 0px;
          	border-top-right-radius: 0px;
          	border-bottom-right-radius: 0px;
          }
          
          .switch.right
          {
          	-webkit-border-top-left-radius: 0px;
          	-webkit-border-bottom-left-radius: 0px;
          	-moz-border-radius-topleft: 0px;
          	-moz-border-radius-bottomleft: 0px;
          	border-top-left-radius: 0px;
          	border-bottom-left-radius: 0px;
          }
          
          span.switch.right { border-left:none; }
          span.switch.left { border-right:none; }
          
          span.on
          {
          	background-color:#009900;
          	color:#66FF00;
          }
          
          span.off
          {
          	background-color:#990000;
          	color:#FF6600;
          }
          
          span.on i,
          span.off i,
          .icon-link i
          {
          	background-position:left -20px;
          }
          
          /* SPECIFIC BUTTONS *****************************************************/
          
          .plus { background-image:url(../images/icon_sm_plus.png); }
          .featured .plus { background-image:url(../images/icon_sm_plus_featured.png); }
          .pencil { background-image:url(../images/icon_sm_pencil.png); }
          .trash { background-image:url(../images/icon_sm_trash.png); }
          .copy { background-image:url(../images/icon_sm_copy.png); }
          .back { background-image:url(../images/icon_sm_back.png); }
          
          .x { background:url(../images/icon_sm_x.png); }
          .lock { background-image:url(../images/icon_sm_lock.png); }
          .unlock { background-image:url(../images/icon_sm_unlock.png); }
          .checkbox { background:url(../images/icon_sm_checkbox.png); }
          .view { background-image:url(../images/icon_sm_view.png); }
          .download { background-image:url(../images/icon_sm_download_featured.png); }
          .arw-down-blue { background:url(../images/icon_sm_arw_blue.gif) no-repeat top right; }
          .arw-down-liteblue { background-image:url(../images/icon_sm_arw_cyan.gif); }
          .arw-down-green { background:url(../images/icon_sm_arw_green.gif) no-repeat top right; }
          .outer .getstarted { background-image:url(../images/icon_sm_start_blue.gif); }
          .outer .help { background-image:url(../images/icon_sm_help_blue.gif); }
          .outer .logoff { background-image:url(../images/icon_sm_logoff_blue.gif); }
          .data-table { background-image:url(../images/icon_sm_table.png); }
          .user { background:url(../images/icon_sm_user.png) no-repeat; }
          .group { background:url(../images/icon_sm_group.png) no-repeat; }
          .group-public { background:url(../images/icon_sm_group_public.png) no-repeat; }
          
          .refresh { background:url(../images/icon_sm_refresh.png) no-repeat; }
          
          /* BUTTONS IN SPECIFIC AREAS *******************************/
          .dc-item button
          {
          	height:auto;
          }
          
          button#recount {
              float: right;
          }
          /* ICON LINKS **********************************************/
          
          .icon-link
          {
          	margin-left:10px;
          }
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        30. GET https://dev.duracloud.org/duradmin/style/dialogs.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (365 bytes)
          GET https://dev.duracloud.org/duradmin/style/dialogs.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 4481
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"4481-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (4481 bytes)
          /* Style for Duradmin dialogs
          *  Created by Charles Hacskaylo
          *  Extends jquery-ui.css
          */
          
          /* DIALOG BOX *******************************/
          
          
          .ui-dialog
          {
          	-moz-border-radius:5px;
          	border-radius:5px;
          	background:url("../images/bg_L1.png") no-repeat center top #777;
          	border:1px solid #333;
          	color:#ccc;
          	font-size:13px;
          	overflow:hidden;
          	padding:20px;
          	position:absolute;
          }
          
          .ui-dialog-buttonpane
          {
          	text-align:right;
          }
          
          .ui-button
          {
          	background:url(../images/btn_dialog_std_90.png) no-repeat;
          	border:none;
          	color:#000;
          	font-size:13px;
          	height:28px;
          	margin-left:10px;
          	padding:0;
          	text-align:center;
          	width:90px;
          }
          
          .ui-button span
          {
          	display:block;
          	margin-top:-4px;
          }
          
          .ui-button:hover
          {
          	background-position:bottom;
          }
          
          .ui-dialog h1
          {
          	color:#bbb;
          	margin-bottom:5px;
          }
          
          .hint
          {
          	font-size:13px;
          }
          
          .ui-dialog .hint { 	color:#999; }
          .ui-dialog div.hint
          {
          	-moz-border-radius:5px;	
          	-webkit-border-radius:5px;
          	border-radius:5px;
          	background-color:#585B5E;
          	margin:10px 0;
          	padding:10px;
          }
          
          .ui-dialog div.hint h2 { color:#bbb; }
          
          .dialog-open {
          	border:1px solid  red !important;
          }
          
          .dialog-closed {
          	border:1px solid  blue !important;
          }
          
          .ui-dialog label.error
          {
          	/*background-color:#cc0000;*/
          	color:#ffcc00;
          	font-size:11px;
          	margin:1px 0 0 2px;
          	padding:1px 5px;
          }
          
          .ui-dialog-content
          {
          
          }
          
          .ui-dialog-buttonpane
          {
          
          }
          
          .ui-dialog .dc-item-list-wrapper
          {
          	background-color:#575757;
          }
          
          .ui-dialog .dc-item,
          .ui-dialog .dc-item td
          {
          	border-color:#666
          }
          
          .ui-dialog .dc-item,
          .ui-dialog .dc-item td
          {
          	color:#ccc;
          }
          
          .ui-dialog .dc-item:hover,
          .ui-dialog .dc-item:hover td
          {
          	background-color:#666;
          	color:#fff;
          }
          
          .ui-dialog .dialog-detail
          {
          	padding:0 10px;
          }
          
          /* SPECIFIC DIALOGS *************************/
          #available-services-dialog
          {
          	margin-bottom:10px;
          	overflow: auto !important;
          }
          
          
          #dc-item-list-wrapper,
          #dc-service-detail-wrapper
          {
          	float:left;
          	margin-right:10px;
          	width:300px !important;
          }
          
          /* UPLOAD STATUS DIALOG *************************/
          #upload-viewer{
          	height:430px;
          	overflow:auto;
          }
          
          #upload-viewer label:after{
           content: ':';
          }
          
          #upload-list-wrapper
          {
          	padding-right:10px;
          }
          
          .ui-dialog-buttonpane .dialog-info {
            float:left;   
            padding:10px;
            display:inline;
            font-size: 14px;
          }
          
          .dialog-info a{
            color: #ccc !important;
          }
          
          .upload-thumbnail {
            margin-top: 10px; 
            height:50px;
          }
          .upload-item 
          {
          	border-bottom:1px solid #555;
          	margin-bottom:5px;
          	padding:10px 0;
          	
          }
          
          #upload-option-divider {
            color: green;
            font-weight: bold;
            font-size: 30px;
            text-align: center;
            margin: 20px 0px 40px 0px;
          }
          
          #single-upload-1 label {
              width: 102px;
          }
          
          #single-upload-1  input {
              width: 350px;
          }
          
          #single-upload-2 {
            margin-top: 20px;
            text-align:center;
          }
          
          button#upload-another {
            margin-bottom:10px;
          }
          
          #drop-preview label {
              width: 102px;
          }
          
          #drop-preview input {
              width: 235px;
          }
          
          #drop-preview button.trashbutton {
              margin-top: -3px;
              margin-left: 5px;
          }
          
          .upload-item > * {
            margin-right: 5px;
          }
          
          .upload-item a {
            color:#eee;
          }
          
          
          #drop-target {
            border: 5px dashed #ccc;
            width: 95%;
            min-height: 50px;
            margin: 20px auto;
            padding:20px 0px;
            text-align: center;
            font-size: 20px;
            
          }
          
          #drop-target.hover {
            border: 5px dashed #0c0;
          }
          
          #drop-target img {
            display: block;
            margin: 10px auto;
          }
          
          #drop-target p {
            margin: 10px;
            font-size: 20px;
          }
          
          progress {
            width: 100%;
            margin: 10px 0px;
          }
          
          progress:after {
            content: '%';
          }
          /* OVERLAY **********************************/
          .ui-widget-overlay
          {
          	background:none;
          	background-color:#fff;
          	left:0;
          	opacity:0.2;
          	position:absolute;
          	top:0;
          }
          
          /* FORM FIELDS ***************************/
          /* Used by dialog boxes and login screen */
          
          .form-fields { overflow:auto; }
          .h400 { height:400px; }
          
          .form-fields
          {
          	font-size:14px;
          }
          
          .form-fields label
          {
          	color:#ccc;
          	display:inline-block;
          	float:left;
          	line-height:22px;
          	padding-right:10px;
          	width:130px;
          	white-space:normal;
          }
          
          .form-fields label.error
          {
              width:97%;
          }
          
          .form-fields .field
          {
          	display:inline-block;
          	float:left;
          }
          
          .form-fields input.field,
          .form-fields select.field,
          .form-fields textarea.field
          {
          	background-color:#585b5e; /* 484747 */
          	border:1px solid #36383a; /* 727576 */
          	border-bottom-color:#727576;
          	color:#ccc;
          	font-size:14px;
          	padding:3px;
          }
          
          select.field
          {
          }
          
          
          .form-fields li
          {
          	padding:5px 0;
          	white-space:nowrap;
          }
          
          .form-fields li.row
          {
          	border-top:1px solid #666;
          }
          
          .form-fields a.helper-link
          {
          	color:#8a8a8a;
          	font-size:11px;
          }
          
          .form-fields a:hover
          {
          	color:#ccc;
          }
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        31. GET https://dev.duracloud.org/duradmin/style/flex.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (362 bytes)
          GET https://dev.duracloud.org/duradmin/style/flex.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (433 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 290
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"290-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (290 bytes)
          /* FLEX BASE CLASSES *********************************/
          
          .flex a,
          .flex,
          .flex span
          {
          	color:#ccc;
          	display:inline-block;
          	height:24px;
          	font-size:11px;
          	line-height:22px;
          	text-decoration:none;
          }
          
          .flex a,
          .flex
          {
          	padding-left:10px;
          }
          
          .flex span
          {
          	cursor:pointer;
          	padding-right:10px;
          }
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        32. GET https://dev.duracloud.org/duradmin/style/jquery-ui.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/style/jquery-ui.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (437 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 34214
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"34214-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (34214 bytes)
          /*
           * jQuery UI CSS Framework 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Theming/API
           */
          
          /* Layout helpers
          ----------------------------------*/
          .ui-helper-hidden { display: none; }
          .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
          .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
          .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
          .ui-helper-clearfix { display: inline-block; }
          /* required comment for clearfix to work in Opera \*/
          * html .ui-helper-clearfix { height:1%; }
          .ui-helper-clearfix { display:block; }
          /* end clearfix */
          .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
          
          
          /* Interaction Cues
          ----------------------------------*/
          .ui-state-disabled { cursor: default !important; }
          
          
          /* Icons
          ----------------------------------*/
          
          /* states and images */
          .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
          
          
          /* Misc visuals
          ----------------------------------*/
          
          /* Overlays */
          .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
          
          
          /*
           * jQuery UI CSS Framework 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Theming/API
           *
           * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
           */
          
          
          /* Component containers
          ----------------------------------*/
          .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
          .ui-widget .ui-widget { font-size: 1em; }
          .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
          /*.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }*/
          .ui-widget-content a { color: #222222; }
          .ui-widget-header { 
          	/*
          	 border: 1px solid #aaaaaa;
          	 background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; 
          	*/
          }
          .ui-widget-header a { color: #222222; }
          
          /* Interaction states
          ----------------------------------*/
          .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { 
          	border: 1px solid #7e7e7e; 
          	background: #6e6e6e url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; 
          	font-weight: normal; color: #AAAAAA; 
          }
          .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { 
          	color: #AAAAAA; text-decoration: none; 
          	
          }
          .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
          .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
          .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { 
          	border: 1px solid #aaaaaa; 
          	font-weight: normal; color: #212121; 
          	background-color: #9e9e9e;
          }
          .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
          .ui-widget :active { outline: none; }
          
          /* Interaction Cues
          ----------------------------------*/
          .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
          .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
          .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
          .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
          .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
          .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
          .ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
          .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
          
          /* Icons
          ----------------------------------*/
          
          /* states and images */
          .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
          .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
          .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
          .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
          .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
          .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
          .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
          .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
          
          /* positioning */
          .ui-icon-carat-1-n { background-position: 0 0; }
          .ui-icon-carat-1-ne { background-position: -16px 0; }
          .ui-icon-carat-1-e { background-position: -32px 0; }
          .ui-icon-carat-1-se { background-position: -48px 0; }
          .ui-icon-carat-1-s { background-position: -64px 0; }
          .ui-icon-carat-1-sw { background-position: -80px 0; }
          .ui-icon-carat-1-w { background-position: -96px 0; }
          .ui-icon-carat-1-nw { background-position: -112px 0; }
          .ui-icon-carat-2-n-s { background-position: -128px 0; }
          .ui-icon-carat-2-e-w { background-position: -144px 0; }
          .ui-icon-triangle-1-n { background-position: 0 -16px; }
          .ui-icon-triangle-1-ne { background-position: -16px -16px; }
          .ui-icon-triangle-1-e { background-position: -32px -16px; }
          .ui-icon-triangle-1-se { background-position: -48px -16px; }
          .ui-icon-triangle-1-s { background-position: -64px -16px; }
          .ui-icon-triangle-1-sw { background-position: -80px -16px; }
          .ui-icon-triangle-1-w { background-position: -96px -16px; }
          .ui-icon-triangle-1-nw { background-position: -112px -16px; }
          .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
          .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
          .ui-icon-arrow-1-n { background-position: 0 -32px; }
          .ui-icon-arrow-1-ne { background-position: -16px -32px; }
          .ui-icon-arrow-1-e { background-position: -32px -32px; }
          .ui-icon-arrow-1-se { background-position: -48px -32px; }
          .ui-icon-arrow-1-s { background-position: -64px -32px; }
          .ui-icon-arrow-1-sw { background-position: -80px -32px; }
          .ui-icon-arrow-1-w { background-position: -96px -32px; }
          .ui-icon-arrow-1-nw { background-position: -112px -32px; }
          .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
          .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
          .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
          .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
          .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
          .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
          .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
          .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
          .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
          .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
          .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
          .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
          .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
          .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
          .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
          .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
          .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
          .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
          .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
          .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
          .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
          .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
          .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
          .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
          .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
          .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
          .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
          .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
          .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
          .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
          .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
          .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
          .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
          .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
          .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
          .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
          .ui-icon-arrow-4 { background-position: 0 -80px; }
          .ui-icon-arrow-4-diag { background-position: -16px -80px; }
          .ui-icon-extlink { background-position: -32px -80px; }
          .ui-icon-newwin { background-position: -48px -80px; }
          .ui-icon-refresh { background-position: -64px -80px; }
          .ui-icon-shuffle { background-position: -80px -80px; }
          .ui-icon-transfer-e-w { background-position: -96px -80px; }
          .ui-icon-transferthick-e-w { background-position: -112px -80px; }
          .ui-icon-folder-collapsed { background-position: 0 -96px; }
          .ui-icon-folder-open { background-position: -16px -96px; }
          .ui-icon-document { background-position: -32px -96px; }
          .ui-icon-document-b { background-position: -48px -96px; }
          .ui-icon-note { background-position: -64px -96px; }
          .ui-icon-mail-closed { background-position: -80px -96px; }
          .ui-icon-mail-open { background-position: -96px -96px; }
          .ui-icon-suitcase { background-position: -112px -96px; }
          .ui-icon-comment { background-position: -128px -96px; }
          .ui-icon-person { background-position: -144px -96px; }
          .ui-icon-print { background-position: -160px -96px; }
          .ui-icon-trash { background-position: -176px -96px; }
          .ui-icon-locked { background-position: -192px -96px; }
          .ui-icon-unlocked { background-position: -208px -96px; }
          .ui-icon-bookmark { background-position: -224px -96px; }
          .ui-icon-tag { background-position: -240px -96px; }
          .ui-icon-home { background-position: 0 -112px; }
          .ui-icon-flag { background-position: -16px -112px; }
          .ui-icon-calendar { background-position: -32px -112px; }
          .ui-icon-cart { background-position: -48px -112px; }
          .ui-icon-pencil { background-position: -64px -112px; }
          .ui-icon-clock { background-position: -80px -112px; }
          .ui-icon-disk { background-position: -96px -112px; }
          .ui-icon-calculator { background-position: -112px -112px; }
          .ui-icon-zoomin { background-position: -128px -112px; }
          .ui-icon-zoomout { background-position: -144px -112px; }
          .ui-icon-search { background-position: -160px -112px; }
          .ui-icon-wrench { background-position: -176px -112px; }
          .ui-icon-gear { background-position: -192px -112px; }
          .ui-icon-heart { background-position: -208px -112px; }
          .ui-icon-star { background-position: -224px -112px; }
          .ui-icon-link { background-position: -240px -112px; }
          .ui-icon-cancel { background-position: 0 -128px; }
          .ui-icon-plus { background-position: -16px -128px; }
          .ui-icon-plusthick { background-position: -32px -128px; }
          .ui-icon-minus { background-position: -48px -128px; }
          .ui-icon-minusthick { background-position: -64px -128px; }
          .ui-icon-close { background-position: -80px -128px; }
          .ui-icon-closethick { background-position: -96px -128px; }
          .ui-icon-key { background-position: -112px -128px; }
          .ui-icon-lightbulb { background-position: -128px -128px; }
          .ui-icon-scissors { background-position: -144px -128px; }
          .ui-icon-clipboard { background-position: -160px -128px; }
          .ui-icon-copy { background-position: -176px -128px; }
          .ui-icon-contact { background-position: -192px -128px; }
          .ui-icon-image { background-position: -208px -128px; }
          .ui-icon-video { background-position: -224px -128px; }
          .ui-icon-script { background-position: -240px -128px; }
          .ui-icon-alert { background-position: 0 -144px; }
          .ui-icon-info { background-position: -16px -144px; }
          .ui-icon-notice { background-position: -32px -144px; }
          .ui-icon-help { background-position: -48px -144px; }
          .ui-icon-check { background-position: -64px -144px; }
          .ui-icon-bullet { background-position: -80px -144px; }
          .ui-icon-radio-off { background-position: -96px -144px; }
          .ui-icon-radio-on { background-position: -112px -144px; }
          .ui-icon-pin-w { background-position: -128px -144px; }
          .ui-icon-pin-s { background-position: -144px -144px; }
          .ui-icon-play { background-position: 0 -160px; }
          .ui-icon-pause { background-position: -16px -160px; }
          .ui-icon-seek-next { background-position: -32px -160px; }
          .ui-icon-seek-prev { background-position: -48px -160px; }
          .ui-icon-seek-end { background-position: -64px -160px; }
          .ui-icon-seek-start { background-position: -80px -160px; }
          /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
          .ui-icon-seek-first { background-position: -80px -160px; }
          .ui-icon-stop { background-position: -96px -160px; }
          .ui-icon-eject { background-position: -112px -160px; }
          .ui-icon-volume-off { background-position: -128px -160px; }
          .ui-icon-volume-on { background-position: -144px -160px; }
          .ui-icon-power { background-position: 0 -176px; }
          .ui-icon-signal-diag { background-position: -16px -176px; }
          .ui-icon-signal { background-position: -32px -176px; }
          .ui-icon-battery-0 { background-position: -48px -176px; }
          .ui-icon-battery-1 { background-position: -64px -176px; }
          .ui-icon-battery-2 { background-position: -80px -176px; }
          .ui-icon-battery-3 { background-position: -96px -176px; }
          .ui-icon-circle-plus { background-position: 0 -192px; }
          .ui-icon-circle-minus { background-position: -16px -192px; }
          .ui-icon-circle-close { background-position: -32px -192px; }
          .ui-icon-circle-triangle-e { background-position: -48px -192px; }
          .ui-icon-circle-triangle-s { background-position: -64px -192px; }
          .ui-icon-circle-triangle-w { background-position: -80px -192px; }
          .ui-icon-circle-triangle-n { background-position: -96px -192px; }
          .ui-icon-circle-arrow-e { background-position: -112px -192px; }
          .ui-icon-circle-arrow-s { background-position: -128px -192px; }
          .ui-icon-circle-arrow-w { background-position: -144px -192px; }
          .ui-icon-circle-arrow-n { background-position: -160px -192px; }
          .ui-icon-circle-zoomin { background-position: -176px -192px; }
          .ui-icon-circle-zoomout { background-position: -192px -192px; }
          .ui-icon-circle-check { background-position: -208px -192px; }
          .ui-icon-circlesmall-plus { background-position: 0 -208px; }
          .ui-icon-circlesmall-minus { background-position: -16px -208px; }
          .ui-icon-circlesmall-close { background-position: -32px -208px; }
          .ui-icon-squaresmall-plus { background-position: -48px -208px; }
          .ui-icon-squaresmall-minus { background-position: -64px -208px; }
          .ui-icon-squaresmall-close { background-position: -80px -208px; }
          .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
          .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
          .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
          .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
          .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
          .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
          
          
          /* Misc visuals
          ----------------------------------*/
          
          /* Corner radius */
          .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
          .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
          .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
          .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
          .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
          .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
          .ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
          .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
          .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
          
          /* Overlays */
          .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
          .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
           * jQuery UI Resizable 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizable#theming
           */
          .ui-resizable { position: relative;}
          .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;
          	/* http://bugs.jqueryui.com/ticket/7233
          	 - Resizable: resizable handles fail to work in IE if transparent and content overlaps
          	*/
          	background-image:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=);
          }
          .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
          .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
          .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
          .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
          .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
          .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
          .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
          .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
          .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
           * jQuery UI Selectable 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectable#theming
           */
          .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
          /*
           * jQuery UI Accordion 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion#theming
           */
          /* IE/Win - Fix animation bug - #4615 */
          .ui-accordion { width: 100%; }
          .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
          .ui-accordion .ui-accordion-li-fix { display: inline; }
          .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
          .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
          .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
          .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
          .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
          .ui-accordion .ui-accordion-content-active { display: block; }
          /*
           * jQuery UI Autocomplete 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete#theming
           */
          .ui-autocomplete { position: absolute; cursor: default; }	
          
          /* workarounds */
          * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
          
          /*
           * jQuery UI Menu 1.8.13
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu#theming
           */
          .ui-menu {
          	list-style:none;
          	padding: 2px;
          	margin: 0;
          	display:block;
          	float: left;
          }
          .ui-menu .ui-menu {
          	margin-top: -3px;
          }
          .ui-menu .ui-menu-item {
          	margin:0;
          	padding: 0;
          	zoom: 1;
          	float: left;
          	clear: left;
          	width: 100%;
          }
          .ui-menu .ui-menu-item a {
          	text-decoration:none;
          	display:block;
          	padding:.2em .4em;
          	line-height:1.5;
          	zoom:1;
          }
          .ui-menu .ui-menu-item a.ui-state-hover,
          .ui-menu .ui-menu-item a.ui-state-active {
          	font-weight: normal;
          	margin: -1px;
          }
          /*
           * jQuery UI Button 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button#theming
           */
          .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
          .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
          button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
          .ui-button-icons-only { width: 3.4em; } 
          button.ui-button-icons-only { width: 3.7em; } 
          
          /*button text element */
          .ui-button .ui-button-text { display: block; line-height: 1.4;  }
          .ui-button-text-only .ui-button-text { padding: .4em 1em; }
          .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
          .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
          .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
          .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
          /* no icon support for input elements, provide padding by default */
          input.ui-button { padding: .4em 1em; }
          
          /*button icon element(s) */
          .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
          .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
          .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
          .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
          .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
          
          /*button sets*/
          .ui-buttonset { margin-right: 7px; }
          .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
          
          /* workarounds */
          button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
          /*
           * jQuery UI Dialog 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog#theming
           */
          .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
          .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
          .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 
          .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
          .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
          .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
          .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
          .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
          .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
          .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
          .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
          .ui-draggable .ui-dialog-titlebar { cursor: move; }
          /*
           * jQuery UI Slider 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider#theming
           */
          .ui-slider { position: relative; text-align: left;}
          .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
          .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
          .ui-slider-horizontal { height: .8em; }
          .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
          .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
          .ui-slider-horizontal .ui-slider-range-min { left: 0; }
          .ui-slider-horizontal .ui-slider-range-max { right: 0; }
          
          .ui-slider-vertical { width: .8em; height: 100px; }
          .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
          .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
          .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
          .ui-slider-vertical .ui-slider-range-max { top: 0; }/*
          
          
           * jQuery UI Tabs 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs#theming
           */
          .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
          .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
          .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
          .ui-tabs .ui-tabs-nav li a { float: left; padding: .12em .25em; text-decoration: none; font-size:0.9em}
          .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
          .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
          .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
          .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 0.5em 0.7em; background: none; }
          .ui-tabs .ui-tabs-hide { display: none !important; }
          /*
           * jQuery UI Datepicker 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker#theming
           */
          .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
          .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
          .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
          .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
          .ui-datepicker .ui-datepicker-prev { left:2px; }
          .ui-datepicker .ui-datepicker-next { right:2px; }
          .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
          .ui-datepicker .ui-datepicker-next-hover { right:1px; }
          .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
          .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
          .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
          .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
          .ui-datepicker select.ui-datepicker-month, 
          .ui-datepicker select.ui-datepicker-year { width: 49%;}
          .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
          .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
          .ui-datepicker td { border: 0; padding: 1px; }
          .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
          .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
          .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
          .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
          
          /* with multiple calendars */
          .ui-datepicker.ui-datepicker-multi { width:auto; }
          .ui-datepicker-multi .ui-datepicker-group { float:left; }
          .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
          .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
          .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
          .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
          .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
          .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
          .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
          .ui-datepicker-row-break { clear:both; width:100%; }
          
          /* RTL support */
          .ui-datepicker-rtl { direction: rtl; }
          .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
          .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
          .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
          .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
          .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
          .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
          .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
          .ui-datepicker-rtl .ui-datepicker-group { float:right; }
          .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
          .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
          
          /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
          .ui-datepicker-cover {
              display: none; /*sorry for IE5*/
              display/**/: block; /*sorry for IE5*/
              position: absolute; /*must have*/
              z-index: -1; /*must have*/
              filter: mask(); /*must have*/
              top: -4px; /*must have*/
              left: -4px; /*must have*/
              width: 200px; /*must have*/
              height: 200px; /*must have*/
          }/*
           * jQuery UI Progressbar 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar#theming
           */
          .ui-progressbar { height:2em; text-align: left; }
          .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
          
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        33. GET https://dev.duracloud.org/duradmin/style/login.css
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (363 bytes)
          GET https://dev.duracloud.org/duradmin/style/login.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 1364
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"1364-1618991490000"
          Last-Modified: Wed, 21 Apr 2021 07:51:30 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (1364 bytes)
          #login-wrapper
          {
          	position:absolute;
          	top:20%;
          	width:100%;
          }
          
          
          #login-header
          {
          	margin:0 0 20px 20px;
          }
          
          #login-links
          {
              float: right;
              text-decoration: none;
              margin-top: 10px;
              margin-right: 12px;
              font-size: 14px;
          }
          
          #login-links a
          {
              text-decoration: none;
          }
          
          #dc-logo,
          #dc-app-title
          {
          	height:60px;
          }
          
          #dc-logo
          {
          	background-image:url(../images/logo_top_duracloud_lg.png);
          	width:152px;
          }
          
          
          #dc-app-title
          {
          	background-image:url(../images/app_title_lg.png);
          	width:330px;
          
          }
          
          #login-content,
          #login-footer
          {
          
          	min-width:750px;
          	width:75%;
          
          }
          
          #login-content
          {
          	padding:50px 10px;
          }
          
          #login-content .error
          {
          	font-size:13px;
          }
          
          #login-content h1
          {
          	color:#666;
          	display:block;
          	margin-left:30px;
          	width:100px;
          }
          
          #login-footer
          {
          	background-position:right -30px;
          }
          
          #login-wrapper .footer-content { padding-top:20px; }
          
          
          #form-fields #button-login,
          #form-fields #button-login span
          {
          	background-image:url(../images/btn_login.gif);
          	color:#fff !important;
          	height:28px;
          	line-height:25px;
          	font-size: 14px;
          }
          
          
          #form-fields #button-login span
          {
          	padding-right:50px;
          }
          
          
          /* LOGIN STYLES ****************************/
          
          .ui-dialog fieldset
          {
          	padding:20px 0;
          }
          
          
          #login-content .form-fields
          {
          	margin-right:20%;
          	width:350px;
          }
          
          #login-content label
          {
              text-align: right;
          }
          
          #login-content .form-fields .field
          {
          	float:right;
          	width:200px;
          }
          
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        34. GET https://dev.duracloud.org/robots.txt
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (250 bytes)
          GET https://dev.duracloud.org/robots.txt HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          
          
          Request body (0 bytes)
          Response
          Status line and header section (373 bytes)
          HTTP/1.1 404
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=utf-8
          Content-Length: 761
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Content-Language: en
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (761 bytes)
          <!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> The requested resource [&#47;robots.txt] is not available</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/8.5.60</h3></body></html>
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        35. GET https://dev.duracloud.org/sitemap.xml
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (251 bytes)
          GET https://dev.duracloud.org/sitemap.xml HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          
          
          Request body (0 bytes)
          Response
          Status line and header section (373 bytes)
          HTTP/1.1 404
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=utf-8
          Content-Length: 762
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Content-Language: en
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (762 bytes)
          <!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> The requested resource [&#47;sitemap.xml] is not available</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/8.5.60</h3></body></html>
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

        36. POST https://dev.duracloud.org/duradmin/login
          Alert tags
          Alert description

          Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

          Other info

          The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

          Request
          Request line and header section (423 bytes)
          POST https://dev.duracloud.org/duradmin/login HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Content-Type: application/x-www-form-urlencoded
          Referer: https://dev.duracloud.org/duradmin/
          Content-Length: 25
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (25 bytes)
          username=ZAP&password=ZAP
          Response
          Status line and header section (568 bytes)
          HTTP/1.1 302
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Length: 0
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Location: /duradmin/?error
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (0 bytes)
          Evidence
          Access-Control-Allow-Origin: *
          Solution

          Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

          Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

      2. Vulnerable JS Library (1)
        1. GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js
          Alert tags
          Alert description

          The identified library jquery, version 1.7.1 is vulnerable.

          Other info

          CVE-2020-11023

          CVE-2020-11022

          CVE-2015-9251

          CVE-2019-11358

          CVE-2012-6708

          Request
          Request line and header section (368 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 93868
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"93868-1329845124000"
          Last-Modified: Tue, 21 Feb 2012 17:25:24 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (93868 bytes)
          /*! jQuery v1.7.1 jquery.com | jquery.org/license */
          (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
          f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.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(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
          {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
          Evidence
          /*! jQuery v1.7.1
          Solution

          Please upgrade to the latest version of jquery.

  2. Risk=Low, Confidence=Medium (34)

    1. https://dev.duracloud.org (34)

      1. Absence of Anti-CSRF Tokens (4)
        1. GET https://dev.duracloud.org
          Alert tags
          Alert description

          No Anti-CSRF tokens were found in a HTML submission form.

          A cross-site request forgery is an attack that involves forcing a victim to send an HTTP request to a target destination without their knowledge or intent in order to perform an action as the victim. The underlying cause is application functionality using predictable URL/form actions in a repeatable way. The nature of the attack is that CSRF exploits the trust that a web site has for a user. By contrast, cross-site scripting (XSS) exploits the trust that a user has for a web site. Like XSS, CSRF attacks are not necessarily cross-site, but they can be. Cross-site request forgery is also known as CSRF, XSRF, one-click attack, session riding, confused deputy, and sea surf.

          CSRF attacks are effective in a number of situations, including:

          * The victim has an active session on the target site.

          * The victim is authenticated via HTTP auth on the target site.

          * The victim is on the same local network as the target site.

          CSRF has primarily been used to perform an action against a target site using the victim's privileges, but recent techniques have been discovered to disclose information by gaining access to the response. The risk of information disclosure is dramatically increased when the target site is vulnerable to XSS, because XSS can be used as a platform for CSRF, allowing the attack to operate within the bounds of the same-origin policy.

          Other info

          No known Anti-CSRF token [anticsrf, CSRFToken, __RequestVerificationToken, csrfmiddlewaretoken, authenticity_token, OWASP_CSRFTOKEN, anoncsrf, csrf_token, _csrf, _csrfSecret, __csrf_magic, CSRF, _token, _csrf_token] was found in the following HTML form: [Form 1: "password" "username" ].

          Request
          Request line and header section (239 bytes)
          GET https://dev.duracloud.org HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:52 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=5E31D0F4635FF98D07FB6B0F6D1FBCA9; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          <form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          Solution

          Phase: Architecture and Design

          Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.

          For example, use anti-CSRF packages such as the OWASP CSRFGuard.

          Phase: Implementation

          Ensure that your application is free of cross-site scripting issues, because most CSRF defenses can be bypassed using attacker-controlled script.

          Phase: Architecture and Design

          Generate a unique nonce for each form, place the nonce into the form, and verify the nonce upon receipt of the form. Be sure that the nonce is not predictable (CWE-330).

          Note that this can be bypassed using XSS.

          Identify especially dangerous operations. When the user performs a dangerous operation, send a separate confirmation request to ensure that the user intended to perform that operation.

          Note that this can be bypassed using XSS.

          Use the ESAPI Session Management control.

          This control includes a component for CSRF.

          Do not use the GET method for any request that triggers a state change.

          Phase: Implementation

          Check the HTTP Referer header to see if the request originated from an expected page. This could break legitimate functionality, because users or proxies may have disabled sending the Referer for privacy reasons.

        2. GET https://dev.duracloud.org/duradmin/
          Alert tags
          Alert description

          No Anti-CSRF tokens were found in a HTML submission form.

          A cross-site request forgery is an attack that involves forcing a victim to send an HTTP request to a target destination without their knowledge or intent in order to perform an action as the victim. The underlying cause is application functionality using predictable URL/form actions in a repeatable way. The nature of the attack is that CSRF exploits the trust that a web site has for a user. By contrast, cross-site scripting (XSS) exploits the trust that a user has for a web site. Like XSS, CSRF attacks are not necessarily cross-site, but they can be. Cross-site request forgery is also known as CSRF, XSRF, one-click attack, session riding, confused deputy, and sea surf.

          CSRF attacks are effective in a number of situations, including:

          * The victim has an active session on the target site.

          * The victim is authenticated via HTTP auth on the target site.

          * The victim is on the same local network as the target site.

          CSRF has primarily been used to perform an action against a target site using the victim's privileges, but recent techniques have been discovered to disclose information by gaining access to the response. The risk of information disclosure is dramatically increased when the target site is vulnerable to XSS, because XSS can be used as a platform for CSRF, allowing the attack to operate within the bounds of the same-origin policy.

          Other info

          No known Anti-CSRF token [anticsrf, CSRFToken, __RequestVerificationToken, csrfmiddlewaretoken, authenticity_token, OWASP_CSRFTOKEN, anoncsrf, csrf_token, _csrf, _csrfSecret, __csrf_magic, CSRF, _token, _csrf_token] was found in the following HTML form: [Form 1: "password" "username" ].

          Request
          Request line and header section (294 bytes)
          GET https://dev.duracloud.org/duradmin/ HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          <form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          Solution

          Phase: Architecture and Design

          Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.

          For example, use anti-CSRF packages such as the OWASP CSRFGuard.

          Phase: Implementation

          Ensure that your application is free of cross-site scripting issues, because most CSRF defenses can be bypassed using attacker-controlled script.

          Phase: Architecture and Design

          Generate a unique nonce for each form, place the nonce into the form, and verify the nonce upon receipt of the form. Be sure that the nonce is not predictable (CWE-330).

          Note that this can be bypassed using XSS.

          Identify especially dangerous operations. When the user performs a dangerous operation, send a separate confirmation request to ensure that the user intended to perform that operation.

          Note that this can be bypassed using XSS.

          Use the ESAPI Session Management control.

          This control includes a component for CSRF.

          Do not use the GET method for any request that triggers a state change.

          Phase: Implementation

          Check the HTTP Referer header to see if the request originated from an expected page. This could break legitimate functionality, because users or proxies may have disabled sending the Referer for privacy reasons.

        3. GET https://dev.duracloud.org/duradmin/?error
          Alert tags
          Alert description

          No Anti-CSRF tokens were found in a HTML submission form.

          A cross-site request forgery is an attack that involves forcing a victim to send an HTTP request to a target destination without their knowledge or intent in order to perform an action as the victim. The underlying cause is application functionality using predictable URL/form actions in a repeatable way. The nature of the attack is that CSRF exploits the trust that a web site has for a user. By contrast, cross-site scripting (XSS) exploits the trust that a user has for a web site. Like XSS, CSRF attacks are not necessarily cross-site, but they can be. Cross-site request forgery is also known as CSRF, XSRF, one-click attack, session riding, confused deputy, and sea surf.

          CSRF attacks are effective in a number of situations, including:

          * The victim has an active session on the target site.

          * The victim is authenticated via HTTP auth on the target site.

          * The victim is on the same local network as the target site.

          CSRF has primarily been used to perform an action against a target site using the victim's privileges, but recent techniques have been discovered to disclose information by gaining access to the response. The risk of information disclosure is dramatically increased when the target site is vulnerable to XSS, because XSS can be used as a platform for CSRF, allowing the attack to operate within the bounds of the same-origin policy.

          Other info

          No known Anti-CSRF token [anticsrf, CSRFToken, __RequestVerificationToken, csrfmiddlewaretoken, authenticity_token, OWASP_CSRFTOKEN, anoncsrf, csrf_token, _csrf, _csrfSecret, __csrf_magic, CSRF, _token, _csrf_token] was found in the following HTML form: [Form 1: "password" "username" ].

          Request
          Request line and header section (359 bytes)
          GET https://dev.duracloud.org/duradmin/?error HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/login
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (630 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          <form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          Solution

          Phase: Architecture and Design

          Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.

          For example, use anti-CSRF packages such as the OWASP CSRFGuard.

          Phase: Implementation

          Ensure that your application is free of cross-site scripting issues, because most CSRF defenses can be bypassed using attacker-controlled script.

          Phase: Architecture and Design

          Generate a unique nonce for each form, place the nonce into the form, and verify the nonce upon receipt of the form. Be sure that the nonce is not predictable (CWE-330).

          Note that this can be bypassed using XSS.

          Identify especially dangerous operations. When the user performs a dangerous operation, send a separate confirmation request to ensure that the user intended to perform that operation.

          Note that this can be bypassed using XSS.

          Use the ESAPI Session Management control.

          This control includes a component for CSRF.

          Do not use the GET method for any request that triggers a state change.

          Phase: Implementation

          Check the HTTP Referer header to see if the request originated from an expected page. This could break legitimate functionality, because users or proxies may have disabled sending the Referer for privacy reasons.

        4. GET https://dev.duracloud.org/duradmin/spaces
          Alert tags
          Alert description

          No Anti-CSRF tokens were found in a HTML submission form.

          A cross-site request forgery is an attack that involves forcing a victim to send an HTTP request to a target destination without their knowledge or intent in order to perform an action as the victim. The underlying cause is application functionality using predictable URL/form actions in a repeatable way. The nature of the attack is that CSRF exploits the trust that a web site has for a user. By contrast, cross-site scripting (XSS) exploits the trust that a user has for a web site. Like XSS, CSRF attacks are not necessarily cross-site, but they can be. Cross-site request forgery is also known as CSRF, XSRF, one-click attack, session riding, confused deputy, and sea surf.

          CSRF attacks are effective in a number of situations, including:

          * The victim has an active session on the target site.

          * The victim is authenticated via HTTP auth on the target site.

          * The victim is on the same local network as the target site.

          CSRF has primarily been used to perform an action against a target site using the victim's privileges, but recent techniques have been discovered to disclose information by gaining access to the response. The risk of information disclosure is dramatically increased when the target site is vulnerable to XSS, because XSS can be used as a platform for CSRF, allowing the attack to operate within the bounds of the same-origin policy.

          Other info

          No known Anti-CSRF token [anticsrf, CSRFToken, __RequestVerificationToken, csrfmiddlewaretoken, authenticity_token, OWASP_CSRFTOKEN, anoncsrf, csrf_token, _csrf, _csrfSecret, __csrf_magic, CSRF, _token, _csrf_token] was found in the following HTML form: [Form 1: "password" "username" ].

          Request
          Request line and header section (354 bytes)
          GET https://dev.duracloud.org/duradmin/spaces HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (630 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          <form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          Solution

          Phase: Architecture and Design

          Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.

          For example, use anti-CSRF packages such as the OWASP CSRFGuard.

          Phase: Implementation

          Ensure that your application is free of cross-site scripting issues, because most CSRF defenses can be bypassed using attacker-controlled script.

          Phase: Architecture and Design

          Generate a unique nonce for each form, place the nonce into the form, and verify the nonce upon receipt of the form. Be sure that the nonce is not predictable (CWE-330).

          Note that this can be bypassed using XSS.

          Identify especially dangerous operations. When the user performs a dangerous operation, send a separate confirmation request to ensure that the user intended to perform that operation.

          Note that this can be bypassed using XSS.

          Use the ESAPI Session Management control.

          This control includes a component for CSRF.

          Do not use the GET method for any request that triggers a state change.

          Phase: Implementation

          Check the HTTP Referer header to see if the request originated from an expected page. This could break legitimate functionality, because users or proxies may have disabled sending the Referer for privacy reasons.

      2. Cookie without SameSite Attribute (2)
        1. GET https://dev.duracloud.org
          Alert tags
          Alert description

          A cookie has been set without the SameSite attribute, which means that the cookie can be sent as a result of a 'cross-site' request. The SameSite attribute is an effective counter measure to cross-site request forgery, cross-site script inclusion, and timing attacks.

          Request
          Request line and header section (239 bytes)
          GET https://dev.duracloud.org HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:52 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=5E31D0F4635FF98D07FB6B0F6D1FBCA9; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Parameter
          JSESSIONID
          Evidence
          Set-Cookie: JSESSIONID
          Solution

          Ensure that the SameSite attribute is set to either 'lax' or ideally 'strict' for all cookies.

        2. GET https://dev.duracloud.org/duradmin/
          Alert tags
          Alert description

          A cookie has been set without the SameSite attribute, which means that the cookie can be sent as a result of a 'cross-site' request. The SameSite attribute is an effective counter measure to cross-site request forgery, cross-site script inclusion, and timing attacks.

          Request
          Request line and header section (294 bytes)
          GET https://dev.duracloud.org/duradmin/ HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Parameter
          JSESSIONID
          Evidence
          Set-Cookie: JSESSIONID
          Solution

          Ensure that the SameSite attribute is set to either 'lax' or ideally 'strict' for all cookies.

      3. X-Content-Type-Options Header Missing (28)
        1. GET https://dev.duracloud.org/duradmin/favicon.ico
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (359 bytes)
          GET https://dev.duracloud.org/duradmin/favicon.ico HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (439 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: image/x-icon
          Content-Length: 1406
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"1406-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (1406 bytes)
          h( ùôîêêêñãÔÛÛÛÿ÷îèæåòå×ÙÙÙòçÚîÝÍöðêçиôéÝòåØùïåþþý±¨ŸòçÛààßüúøõíãÂÂÁûöó÷ïæÛÚØþþþÿþþýúù÷í䤤¤ééèÏÏÏëØÅþþÿòðíøñêìÚȱ³´ùóíÏÏÐðâÓîÞÎçѹøñëãǬú÷óÉÉÉùóîüùöñâÔÿÿþÆÇÇÇÇÇìÛÇýûùéѺñä×÷îäôêßþýüÿýüòæÚüù÷¶¶¶ÿÿÿéÕÀÞ¾žúôíýýý÷ðèõìãäåçöîæ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@!2@@@@@@@@@@@@@@@@@@@@49E=+:0.?3%
          A6)15H.'G"+#E(+!<7C-@;@ 5*F@;@@>	8B/;	
          >@2@@@2@(,$#@22@@@@@@@&@@2@@@@@@@@@@2@@@@@@@@@@@@@2@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        2. GET https://dev.duracloud.org/duradmin/images/logo_top_duracloud_lg.png
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (380 bytes)
          GET https://dev.duracloud.org/duradmin/images/logo_top_duracloud_lg.png HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (438 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: image/png
          Content-Length: 10073
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10073-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10073 bytes)
          ‰PNG
          
          
          IHDR˜<šOsÙtEXtSoftwareAdobe ImageReadyqÉe<&ûIDATxÚì}x\Õµî™Þg$Ê¨KV±dË
          W؎
          ØØÆár“n€Çƒ$/ðø>^ ܄|¹ÀKƒûBnrC(Ø°
          î¶Ü»\$«ºFÓû¼µÖÒ,%l&ŸOû›ÑÌ9»þ{õµG‘H$¤/Ñ¥€¢dE…¯
          ,41(qögß]º.àRIÆI€Ò@ÑBѱW
          MbàŠ@	C	aï£p—®K¢X*‘“	ŠŠ_MdDÁ"*?/¾úðóíEû’ŒX ŠJ;”L|̀bÃï´x$Àä†Ò¥J7”^(.^)Ú%}RS(Ÿ›A\IìP€ËŠ r@)åX«{ÂÎS½»ýYAsêó96½·$ËØ]Sh«›Qž±>j†Ò
          ¥'(ZP€æåK²*«+Î÷ÁÏÀ¸H¡°Š¡”°f¾µ»mnS?í|ë+´{o˜ž·ÀVÿÖCiÒeJ@°Ë/È.lpH•‰%æ`A©zswÛ²µ:j>jÝ×OÍÛ¼ô²Üwàí)(P:‘¿ û¨û¢É`*Æ®	ÿùnýí›\y§âU{ÛçÀ$Çh1ò¹	#„ÿ_º¾¨c¬Ñ„2—`‹Õç.›Qt¤é½yé/}ÖÐéMëù,‰ÍÑÛûœóZ•ÿê	9a¦MƱý
          ýdWãÙÑä×/‹ÜöE£`*49¹+J9°Åë?\có,=·Í.:ž›®,¯5Ä8Ö%Ëp[êzª6ï®lîñ§‹gVîi¿”€¾	E¶8I‹Ï†˜öªdf8jœ,acìË"»}!d0”½hz(lñx›{ñoVŸZ6Òý:2ú/³‹êfWÚw †Èå©aƒ’%ûFmÛìu;&ÉÏ«•‘Ç¿^ó—4“FÈcmhÎ  T¸q	`Q¬7€æ¾«ý<ís/ƒ!HÌ~Eï%\¨“yRY
          )‰QôfmۜÑØá¿Í/­­ÌµpF€ô⇛ӳúúnš‘ï󅢪­u=5¡h\ó̺Ó7?rSõ
          5=c#À<HéúðÕMm
          ŠöE¥fêÏ°hQȕCE•B	ȅ#Ë@ðl”Q
          ÷Y»ëû¦dŠ”ëÿÜ4î}‹A-LÇ¡4IƒFT4ÜxªÄþ*FÆÕè¿^U¼îD»§°Û²µôúí ß]÷Í«Šv[
          š®¦n¿²­?`®ksXTþˆ ~Št“ƫת3Ë3•d™„™£Š_0…Üü¢‚LýOK‹¦³”tᤤ‡,ìA\lb5dU'0}w}ÿˆæˆûUìp탷G‘zurpÁÇè•ÈÊBؾø_û•ñÙ;^ÝѲHÜò].”eç3֍Gºf/´6,›š·€v@Jz_dMTýOD­Èj2ñՊ€£þŐjpÇ»‘²ô#@$— Ý¾ŒÔöónx{íX‚‚`½Ã¨¾	³~ԇÒ° &ûƒ5ûWz‚Qó…Žùh‹{Ìi§·ð«Óó7@=k¥¤ï3Jí}Ѩ˜úŸ.bA&4ˆæ Q4ÿL—¯üƒcÝ3@k+ ö˜€?Z,Î26Ϫ°“m¬M¸lºÍ¦£¼”ìIŸÚæâ)Ž£¬V|Î=¸R›²a¶#;Æ¿qeÑ_Vìi¿©Ã,Ъ•á²sh•§³¬ºî‰E6ÁþT¦¢¦_áñ6OÙI§'›êòRÀ€Œ(r€±èØ(b„”bþH°ÍpI‹L™,
          R¨ViŸ7\ý·ÍM_í¯â\u䥜7ÎÈó0‚%Œ¬µÔÙ¼ò±×ÎI5GühIå?à­ìHƒî÷ùhp)ýM#­©­¿‹IÉ°žAO›§½?Põ×gp¹Pȃ?»eü3é&í.ø·•¤hSvHŒPbþàaD~ž´H%ÊbqÄÎ.é÷…'>ýöÉ;{<¡³ó»¡4?o§+”NßÂå>»îô·®›yè[sŠ7ââêe
          8{,w˜]Hñˆ¥ž·{‡Q±.nŸïAö®f¬ŽØ‚Ñ!¸ßXíý¿ïœœJB¦LÉ"q5Èeó¾6³À‰,Ø+%C…LÑ1àØ´ØE}P¼Z™=dŇdÉ/+‹$wŽ`iÂZúÔªáঐ™]7Ù±'^L˜´Ãê67ÍlFÜ·íDÏDo0šý¯sŠë,úÁ¡ì<Õë8¤†.”Ù>ji±~|
           (ø‚s’Ĩ^AsÛ좠®™T)€­Dtg‘,¨Æþ)X¤ôX¤áaEr/ŽË…uˆÿ«ðYÙ§
          0æŒ6!{ÌûïM7ppM*Në¸÷Ú²õhBè@Pˆ6M/Ëè¯Èµt<½êč]î59Gãr_ڕU™­­½3Q~lÔ*%£Âª­¥ý1FeRít±(5i¹ÖÜt½£8Ó8žX¥xuº‚sÓô*ö‘æȆÑÚÔíÏuº™ŠA’¶ßìµÍ,dúèÆ~ù?+ S
          €’˜ì Æ)À%(MÁÞ3ýè~˜|€ëi0bA˜ÚQÀ–pÂ{ӌšÀ׏M<ýö‰¯u
          „ÄΖ„PÿÎ>gùhý(´ÀÈvváë Т0þÊz½(+v¦ÞóÿÞ­¯ùßËÆF›(~œ'KK¯¿`ÝÁΩ'œž|·?bH}Ö
          sQS`­ûöܒ·˜<H2ZA–øÂµDR5ÌÖ¥Gp‰À¿ÒMǺ¯àÎä¹ã²ÎHƒ®›zY²‰=²è]ÆèŸ\uâfþüH,œw÷.^äSÓ 
          Aõ¸Id9P«Qù="àñߗ›víĜÌñ…6—Y¯nÈ<ÐèÊÔùÃê Û~²wÊéoُ–Vþ7P43V 7*Àò©uՁb‘Ö£GP˜áԌڗ=Æ{(àσÐ^‡ jÇÝÞÃá#ùILP¥ÄÝʔ¿[{êëô¼ˆD]4ÙÑèEÕ+÷´—Á&f”g¬E­‘ü…ŸvjÙ¤ d=Evã™SNï0à
          üÚÎÖ*(©!.<ÿAãm )+™]±‡¢Iy ¥ ŒÀ»è@S_pQr…å‡t”%HXÍDÓD±‰áà’¾:*,¨ÖŸ`¶ Ùº?¾Ð¸az¾´ëTïi&­ï;óJ¶u“…Ý«'äPL}R0اm-KI_d×Ô1éÛ·ÖõL#Eå|.¡ôÀækžQ–Ñ	r\ÌŒªÿkCC—7Å{ fsgWÚÉéßŔr´»‘²y|ÛEõIR0îp¶£Œ%ìEŽ~_8ooCÿض¾@žJ©Ð©UJcŸ7¬çv!—?¬—’NàîºøìÆÃ(ƒ4Í(+q,qfñ'—’ëôJI·Ï§
          °0ö¡³,Ǽ环”þù½CK£±¸95æŒ_ÂV6»2³õ_fnBŠ$€`¶_² &»5U¡ye{s•x­)´fX
          'Ž™F²`'3PKdêO˜z‘b	ÖWºíDÏÜm'z¯¬ïôž«œdJ¨ÂÊÈeäÁ÷~|F'
          Ï
          
          3»Tˆ±‰F&ÙÈ|¤åM)IC ,]¹·½&UIàºoaù¶Ê\Ëô@ôâ¨"ÝîPáHsZ¹ðÃóŊð¢|»ÁyÝäÜ
          ‹äÜÿEM,þ¤(˜R.SøÖî¶ÖèXt¾€Luwi{ñQŒž1fj ن´Ô8³p“`ËÃ|>õhRÖçÛ$úè–MÍë¹ÌrÒéÉ!p=t}Õª»á€”L4qã‹WÍñ6þ|û ØqC§¯èÙu§ïX<%·à«ÓòÞd›/œÊ->˓£€bU§‚KLÚÄ¢´¦r‡¹Å Uyg–gm1š’Øe¸:ߺ_ôº¤d0އ-XŒYÍSYÒg-,™(k‚j=8VYNù±ë¹÷êoíñ†³¿=§ø®ƒ¬6diAàEfw 2¢6,L= 
          ;XدL9t­Þï¼ÆnÖv]Y•IÆY3ß|æ&X¤e큎yüËyã²NÃΩaµ…¹EdÖ5©8-ˆƒìG60p.Y‰çsޒb¨%­’ˈ}°èíßX}PJ†	Ñ|\J›J°·NÁþ±zÇ·@¦Õf˜µAظ] àŸ„9îC0Šglí½º£år.¯­?ÒùØvä8‚ª…|{16å'	°!‡lç@(‹¾r¼ÀµKJ&®öKÉèÑ0#ÕY¼˜$û³4[”Í+%C‚”ÒðÐ$ò>HìÞÎYö E
          ]+%cÊȔ#ÖÂ\aèøђÊ6ØôÓßÜÝ6UTâìæ;v€|W/}6Çg`
          Æ
          BA/-šìX
          àڊ¶-&”†ûîRËǎ
          @cïY_H½#„Éðx>n–‰Dl“|›1¦”Pö…_û˜íBPª˜D÷+‘£ÊÕkÑŽÅ@™˜/nîñ[`½«LÛ'0ò«‘Õ]Ã(’ÍP<;†^ã)þ.š(©*ϲùÆéù+‘bu"õêc¼’µKZ(µ§Æ€Dîë‹IÃ#b#ùژ¿SÅJ*åÀìyºËå~ Ù„„BãáŠÅˆ†ÅÄñ0q3â
          3
          8ÄæڏÏñƒ[ÂLÞÓ2¥ÉʄX¥ýt‡wR<1Då(¹E›²)ãlÎ	¼¤m*ؚñ£¯Ìc ÿ¯f,NÏ¤6Οñž03Øщ3B˜JÃcçEÞ»ÿkIå+xO/ªç${řÛHÇv`‚œ<:fߢèÞ¶l~HI¡gmÄû »Pb`i¥ä)<6éìHžÄA,Œ§¬©8BdÓ#[y:,8çV6RJ;nÅïøùf:ü8?|øméŽy%/?úÚÑJ³^íÃöíØI~ҁÛÇæÝÏØ5­•†mª(k{ <õ|´g™°‰Mi?ÝX\ø½;›õ(˜*މlÒË´Í4lÓÌÚP²I§#–H¾ðán$ë<ÅwɓŽ,G)%£d©˜`R2´Å÷‡S¨	))ilvüßÌ(Qò¸™‡@Ã@È-ç^œtót¤¶ceóÍ؍ãäóM ¡p+>ãÇöÜLY2‘ÁKÖ©on…ÃÜ&%óÔ¬_|#ù¥dHP/͝ž¡“‡diJ­Òâ€EGÆHƒ1JÙ8á´øAFEúÛkÅ	6³Eµ3ÒÄÁR[¤9ØFv2.
          £&êAóãD÷`»M¸ƒ…Œ#»RáóÙ¸Iro¹å–{GÝïÿûÕøœÜ'
          ÌCpé™"
          ŵjÛÓÐ_¢@*
          ³ϱézíÆVœ‡>)™²¦Ãúø(]LøNàø(Ð2Ûq`»6Ðø읮 
          e‚˜I§òWç[›pÜ]h²hÇ5 yÌÀ¢d_ÁX+QLJª±¸h¯”R¾³Œp/«·ƒÉÑQ/%çÄ¥áA™²£fH”£jkkç̜9ó›#ÚXŠ‹#Þ»îºë0,Ü1|ÆȄM1Q9°pOˆû}ôÑ·{ì±å܊Íî+xöÙgçÝwß}w‰{÷íÛ÷ú”)SD=¦ÒÒÒ¯766ÓlŠŠŠb555žx`ßüùó÷³Åäò…)‹…«Ü»wïô#GŽL†1€5á÷ä¶	 S‡“+_„¬»üÚ֙§œÞìp4~–Â`7ký"?`hÉ~é/ïx»ÇäöGԓŠÓÞ½÷Ú²?2“	ݹhÁ/¯]¡1+÷¶Ï:ÞæÎð£gisVƒ&4©ØÖ°tjÞÎ4£&ûJÁŽé SMùÓÆ3÷ºõ”’´÷\Sö<.îã2wÙkꓫNüQï¿Í/]7½,£³c ˜÷â–æy Už¥ðiÕÊDÝà™\œvZh¬6£¦	.@æÿùÇïnï\­V)üv³îh0Óýò¶	ßG`Ê1sDUhgeÆŒÑ4‚¦¦&
          ”ôõë×ϙ={ö¤å˗¿ÔAÔLÁ(“|™Ífb»=R2ÏQCmY,–Lv¯?7hµÚ³š››UPÒÞÿýù?þxéƒ>ø&[</NªÁ+Ü(•ï½÷Þüºº:y^ýõ+n¾ùæ8N<åB*˜¦%½JŚýW®>àÀêG¶U‡>ӈŸK½Þ°ñýÎYM=¾üûU¼+ÆfÒ«U*…<§bqÌlìÄ	†"Iß;ÜyõêýÎb(6ÔNšI#iUJ	4>Éå‹HݖºžêÚú¾ŠoÍ)Ù4mLº8!ãO§r(•ƒmê4*¢Ž}L¶¥µM×j”Ck«VÉïUÐV–ŸO½Äø:}V(—­?ÜUsýÔÜ=sª³ö `»¹©úõ¿tx¬#M_wÊé¹6‘Ìl:÷–³-™LÂ⚨+Vơ̂7ÏŸù_|ñE3,–yÕªUi'NœPnß¾Ý û*¼ªdV¤$D	åË`0™l¡eäZV& Þ¡Ô/½^oÃIѪÕjyÂðƒøñ‹_%RïÚµKó³ŸýÌæóù?ýéOK'L˜0sá…}–¤LV$ýN§³jÛ¶mvªÿå—_kÆȊd;j¤xy(T>·¾aÙ¾3ý¹2èõjify†ëªª¬Æt³¦&\ŠÆuÇZÜYïí*rº‚gD	½ASbE£R˜ŒiƉÀ/@_{ céÆc]¶€UP
          NßÂɎ£VʋjfmîñînèË*ª~ÆÿÚа Ûo¹n²c/n(=$ƒÚT¶icr-Wš,j…bh¾á:%€ÓÏɟÉ6…~°¸¢C¥Tê;¼ºÓ^˱VwF}§W	@×¾¸µyv 3-œä؁sדaÖ6[
          jg^†aƒR¡p1?εH
          ³ÑC‹Ca$€ Õj•Ž¼óÎ;ÅÃÊ'Ÿ|2ýž{î™úÜsÏYΜ9£½âŠ+××ׯ•’1åCƒÐh4$8sõ{(Ñ€4¥‰ïeR“‘L&“gΜ9	(q(®Y³f•éµ×^›«eÊHß
          š³cǎ±@í†vão¼‘~ìرâqãÆ5’mIy.|ñÛûÚç¸*s͑;æ•î‡	¤³'üzJ–çŽËRB‰¿¼½ùr[6%_	;ö‹o2Á‚K×t~uã±n³W¶M¼÷Úòý¹iúv¦´Ä€ò3'§”¦åõš¶z_‡µß–ÞÚÝ6£,Ǭ̵ˆþ«5j…M5¼MÒxÕ)Q.å µ)…LðªU"@ÔÄaŒ¢Uù”øÒËr-â4Ȼ۳û ý7jÛ&uêÐUU™²Uá¡ecÿ&%N %p(K^Éì7²ÍHÁòÓb±eψKóþð‡Ý?þñeí±¡¡Aÿý÷ODžÍd*¯Ø*fCJmK
          ß«Ù½Cö7êBªí
          dÃ`UU•ìƒpq2
          lEûÙn·Û±zõêL v°áPX¹¾?ýéOcP¤éfb¿EHrñºƒr¸K^º!úÀÒ±Û\õ8f‘'Ï•sÿ?~Ûì¢\6ö?Q¦‹HãD=tH%åñMÇ»í;ã’Á‹{hYÕN—¯cíÂrS•µuÙ´ü~3&¶,ßÕ6™´O 6&ˆ"Ù¦*Å8,oj¥”d…ŠÁ÷À*/‘€G‹M%ú$AþÚwûUEí0ò}«ö¶OB.`BJEæ¨>"$S±Tá5א/zP¨;…üW÷­¿üå/Ν;W¾÷¯ýk#͆°üfA?ËyMÅf“M’T*Uœ-$Û$gëÖ­•ÀÞå6¾ÿý,Y’@6™…‹MZ•l´¯2°+éþEåPc¼Ç-ŠÈrªÅÏØêlù„±(ÁøÙ¹ƒ
          fÊêvK»|%ÝîA³È4§,zu‚ëÖ½‡:æ ejiځË+ì2ˆ»}Ö#-bÎ-@t/cv1v;>h„ãn@°‹öEiSM¡í(ˆrÇüݺƒãÙZû™Fía揑Ý)Œ‚…pòœˆè#0Áfzî¸ã9‰Áëõ*Ö®]›ÉŒ£Óe§àØŒ®··WÈb:Ô*Ìð§Aö(›=Ö¬YSØÓÓ#×ñÝï~7 “ãà;::ÔO=õTµ”LžÍÇ÷iG[ݲÂQî0ûa§’kë$.ð	ÿi¶³Ob(MÛÀâg¥§ò(“4Ð0'÷zMH †®žs¹C¶sëo`m‹ïueûøk[ºiŠì8Ù+Ï7L•öc$EãÆMp
          æf ;ŠE¼ïœPdkͱ
          F	iqç3å%Ɣ­ §úp€1Ó?Y…»¢‰ô_wÝu-vû ½{÷n3s«|œ¨¾’ä2AÆm‘H$ýàÁƒÙ—_~y*€{s=i‰*Ò1aݺurn¿ýöà˜1c¢ÕÕÕþk¯½–„ýRfLTÀêuFŸ7,›fWÚÛÐì҉àéDìJ3iÇR2I(>²'„l£7µ9Fv¥å[ÉhJ)g‚Åx €h‹¢,p¾åïAnÉK\à>_Dv/¶>î|§^1æòëeí÷eZtíÔ~Ç ½N›â2×YBbrÑù\äù'ׁ/;;{ ++KfUýýýÜÿÇY/ç•¡$€½ðºË.»,¨UÆäɓÓO:%ñðÃ7ƒrq5Hî$Y–
          W÷ÉÏç;߀H€²‘¸õÖ[#ho3mÙ²¥–ƒÔk(ù¾+Å%&<ʝÔXRÝ"#á‹gVi<¡¨mHkÖ(yhw€É-Cí0W,@ƒàï
          "ÏwC§W^X…¤‰€)Îãý¹(–¡ÓŒ ý~™ÜGa>a~TõhXRJñb#5?ò,Ðá½t ‡„,MÚ¿¿B¼Škƌ±W_}µù‘G©Åßƒ‹"§èƒÂQ¶|ùrÙÌRXX¿úê«iÁ7ÜpC°¼|0*ù7¿ùMôÍ üª¤OáÒ¨”ѳ䀏X9×=¼(?"ÀFâf#pãB"/È_%ËE]]]Öîîn%Ûq<u^6²0F•R„¶¨¡ÿCŽëE‹
          -ÈÝwßêÔ}Ë-·t2hwÐh²6oÞ\~àÀùþŸüä'¡@  öûý*(j`«‰o|ãq4Y¤Œ–‰Â·q|¡u€Ú©ksg3׉œnà×p§¸p/±ã§†vð«æ6aþÏ@8F¶G’1y`oÅþÆšnzç@P‰š®¬Y'¤×-FšçdtˆbD€%F*µOÚº„û´OHM½1j2³ò;…ÿ֏‘ûø„P
          ÚZÞò@-ú™€'¡¦§f®šLŠNu˜yèÄ¢|'NŒ?ôÐCr}Ï=÷œòÍ7ß´0­’BM¸²Ng!Ç*Lâº÷Þ{
          F£1Íd2e@I‡÷ÖÇ|h¼ —`t 9Æ@›“ÝÛ ÛÁÈ#Q€c¶BŸLPÈ$bC]JþŽ#ŒQ(òéÒ͚«AM@ÎBÅ$eAÙÄ#ڀb”’)~yxOF[_  ½0od!9Š¦*ÂÚ¤911/m½rp3›ïÄÙçðÓíؾ,«v{By½žA
          ؑ¦w1ö¸}(À :)yH‰à/"[¥Ý*Y¿ûÝïd£$,`~¢,>fó ˾ªKÑSJÑõõõ²Õ?33SÒét$τṡÎüêW¿òWUUÉÜsÏ=¦={öؙ{'Ÿd)­Æìܹó¼Éñ+¯¼bãTcB±MhOÈcføI	ýO®,øy%ZÿpŽŒ*fhU
          ßdÉmDÆØNä¦Èå¤[¸syDzvʱ^ÑÎ8œï’P$ž}ËïG%abqšœLÂK$”m)Ö1ÿ·Gã	S]ƒçl$†¥‘ƒÏSûâ}ö‰6OAKï`îʸk*8×=€)Ñ4@Zœ…K÷.ÃF|ðÁ)›6mR¡0M‰	²fD‚?€!]b'?C!»Ñ—	 M4žžžN‘®ÁX,Ff9Ž„}Ù¨,Yúá8Æëõæ ÈÅ–y<ž|Ðs€]Ëρß
          Ûò0”-PÖAÙe/”ÓkÖ¬‘7@{{»ê™gžÉ¢ø­…§…ËFøŸ[_?e,ŽY’§áëtüLŒc,°rÜé&áˆ$.`3HÉÜPa{SÛÍÚ¾Ê\Kù5Wîm/ó£bÂÀ;…µ3_i¾kz§í=Ó¯!ÇÌòaÎè2jU øÇE²#1˜†ó.’y¸Å=t¤{–U‡‹`HÚ2Gq ('`ŸÄkñþÆþI[ëzdÒjÔ¯›ì؃ëÝ/’&1cԂ‚é™ó¸'¼À5ý駟–O·)--
          ÂBmC{Ž|"h|²LóÚk¯™=š‹;¢w©XGkkkæ[o½%×QQQAñUr`]4•û‰DÄví6mZ×c=&,mÛ¶M	Bþ4ζoß^V[[+eá…曘Ýî 
          …íªyæ̙ÍÕÕÕòøžþùLRɁäwÏ—Õ>hÈô«Ÿ~ûÄl[£$qÑjpU¯îhýö¬:q…)™ÜÓàÜ+@öO*²í»lLº_t*©þcEÝ§+XΨåD\T¹
          pÕæºî+ßÙÛ!²¯äº¿~yá.œk1ç`œ!ιÐhrå³ù‡ýÏí÷Eµ§{m(?EáA½ Á…IýE
          –.%‚G¬wÉÎS½Sÿ±½5‡L,K§äîaæ‹?54h,Œñôp8¬w»Ýv­V«‡,Z¹reæÛo¿.œÝ®,îj4ÄuÓæxꩧ¶Nš4ézaìÖY·}ñâÅ-z½> |/½ôRÉÏþs;ß
          !|ÿö·¿ÝÉÃy`ƒ‚°p:Dù裏v¬X±ÂZ¥ùü£åšk®©\²d‰˜`5—LÀFÉ(ڄÆÒ”Ð]@)}W]uUáñãÇÍ@A
          ‚
          ϝ;WPÈèÍ3v´÷æmqgžtz5?}õèìéeé³*ì
          v‹¶;‰«Ãј¾¾Ó—¹ápWiK¯_T)„2j"+E»ؖùL`K‰H4.2D_}z­Ê	»ÿ}—/¼`ç©>}—;¤{âÍã3eg÷$ÇiƒVår‘'±6wû‹êœž¬.¥ ¬âºazþî©cÒk¥äI=K¦86ÕÖ÷ÞäòE”Þx¦lAMvÚÕrT„ñ¸þ”Ó[°þpG±·¦çF
          \	E#„%$%°Ù4•R©õ…¢â´î,˜‘†¨¢öoœž¿6âvœ_'*[áÑd0Ü9pÇL>räȼ	&,>—¸wݺu«-hVŕ D/xøᇧÑý"bBêë듋¸@ðN•Ûà;‚|\¶Üß%Âsn¿ýöú¿ÿýïi3>|Ø1kÖ¬…L%Ü#mܸq°EÃ]wÝU}èÐ!)'''ÐÑÑñ<³„“œ AV/¨D9l–é@éæ¹\.iÁ‚Íëׯ_«hßþ÷-Ms¶Ôõ”
          ™€Ú[–nÉŽJþP2[®Âav>xýØu¢ß+ö´/…E1+(õúæUÅ»ª*³åœÌÕû;æ®9à, ÅCÖ%·#ˆ!¯Gä•^79w/€óô tà†T¸üD»gæ3ëN…BŒ´ØgY´`õL,²µüυåk)VÌÙ¬|i[Ó5°¡>t½u Ý<«`לj\äÉhFc¬_%…PÍb©{ê†Åë­ÆcÀþÜ,à°یHVaDž™ ®ï‰'ž˜	À°KVWMMû׿þõÐ>IÉs±dÁ(§¼Ü^ùøÎï}ï{i@ñ.ojj’î»ï¾Jø,,À%®;ï¼s3¾AJž/æÅqúI˜1cFpìر3víÚeÜ°aCQcccOIII~Ÿ@pÍŸ]öFmëØÁá˜N8œ=6sÏÒËdv!¾4xÑPƒøhæ¨ÇƒTU>9hñ‡kú˜ô’{Ûglre
          p¤¶­Ì³´‹ô¿B»±Ç֌HÂ
          ›g‰ÿâ֚®?¿æÚºvO†-–0+@_kúìÂùäÌËT62š&?Ãà›Pd;3|ö›Q#Ž×:ƒ®Âv)™$=z+&;X¤ävŽ2`I^ߊî”n\@òpª+뱠Ʀd	nœ¤VÏ¥A­+ß{Y0¡µ2úµZƒ4ü<
          /öÃÉ
          ÙÊT,VlHíg‚œ´Qæ Pf3s‡(RúߏD{ý¢n>“ Ë\ln–ÐÍÂÆM,J—Ä–a€*/«'7e¾­8ß*&þxpžé$Ä0ÞC‘¼9øÜHI.6rŸõ±¤’ćO,†œþbe©I|b{™áeñßܗE¾6+‚ÌO{á1ÞÞ#%Ï+¥Cã”,$ÚÆÆ¡Tü¡_ç`‹åg	*>ì“JJf­aýÊ`}çbÆ^Ûtdõ/‘|†2«º¤äoXR€Ì“ri®zRBbÌÐÉçۖ2ßAiøODStø99¸-)I”üKÇjÑzS¢Ë9“¡¬":˜÷\ik„hJÙ¢CábŒLª¥‘€&/žâës3!‘bÂôl1Ã)uRv{‚M"ùõø¹ó©¿gDy´QCa!6d¦ÃóxVQx„ñ“‘“Œ›©YH4VN‘ulŽøÔó0úE?O_Í,îfÜÈ)XXžòb£qZÙ8%¶‘ü#¬wDžzN€3ñVþ³t<!3>Š?L•R—:ÅqeõÅ”Ìažz´÷,¨SØIL:ûÜøÄfµ4<§0!}B4O¾Õ¦´5Ò\H,ô\âüKgÿ¤õM)
          OòU§xRbŒBk\6ß±Úçkğ“Rúa`¿à£žõ€ýK×¥ë“vv_º.]—véúl]ÿ_€‚D"9‹gjIEND®B`‚
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        3. GET https://dev.duracloud.org/duradmin/images/wait.gif
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (363 bytes)
          GET https://dev.duracloud.org/duradmin/images/wait.gif HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (436 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: image/gif
          Content-Length: 1583
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"1583-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (1583 bytes)
          GIF89açAAAÿÿÿEEEÔÔԛ››ùùùááá^^^€€€ííí¦¦¦²²²TTTŒŒŒjjjÈÈȾ¾¾ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ÿNETSCAPE2.0!ù	
          ,j`@
           À€8 € ðâAŽ 2h`€@B8h Á‚”¬€c̔ 8ðÒàF
          €ð dB }PÀ€ƒŠ4êPÁх'ÒÜ*0 !ù	
          ,np`À<  A.„``@(€€ p`€@B0`°‘Á‚0(©€Ç˜(U
          8°òe̎€€ AI‰H0À€Èš$P°±¦ ÖTèàAU!ù	
          ,p €x€À	0ð(@4`àà0°Àã”&ª4@`!€AÂTÈ`Á(xà€Aš)@(`@Á~$ÑÀR+>@`0åBY!ù	
          ,k €A
          <@`€(p°‚ØHQ
          p0 @‚Ž
          ˆÐÂ28`P €›2x€@&(ð &ƒÝx1£˜6#6|H æ@„ÜÊu`@!ù	
          ,i €A 0ÀÀh0` D$x€40  "‚‡28™`€ƒhpB‚h‰$M†P` HB҄`À"ÆJ.lˆR"Aƒ¢Zµ!ù	
          ,t(€	$``€àÀ @$ð A40@@À	<p Á‚00 ÀĈÉ`À‚˜<0Ä  @‚@0°€@EJ@² „&K@@;
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        4. GET https://dev.duracloud.org/duradmin/jquery/dc/api/durastore-api.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (378 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/api/durastore-api.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 17975
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"17975-1638286296000"
          Last-Modified: Tue, 30 Nov 2021 15:31:36 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (17975 bytes)
          /**
           * 
           * @author Daniel Bernstein
           */
          
          /**
           * Durastore API 
           */
          
          var dc; 
          (function(){
          	if(dc == undefined){
          		dc ={};
          	}
          	
          	dc.store = {};
          	
          	/**
          	 * @param String spaceId  space id 
          	 * @param Object callback The callback must implement success and failure methods.
          	 * @option Function success(spaces) spaces is an array of spaces objects
          	 * @option Function failure(info) 
          	 * @param Object options
          	 * @option String marker - the last content item id of the previous page
          	 * @option String prefix - a filters the results to show only those matching the prefix
          	 */
          
          	 dc.store.GetSpace = function(storeProviderId,spaceId,callback,options){
          		if(options == undefined){
          			options = {};
          		}
          		
          		var marker = '';
          		if(options.marker){
          			marker = options.marker;
          		}
          
          		var prefix = '';
          		if(options.prefix){
          			prefix = options.prefix;
          		}
          
          		var recount='';
                  if(options.recount){
                      recount = '&recount=true';
                      
                  }
          		
          		return dc.ajax({
          			url: "/duradmin/spaces/space", 
          			data: "storeId="+storeProviderId+"&spaceId="+encodeURIComponent(spaceId)+"&prefix="+encodeURIComponent(prefix)+"&marker="+encodeURIComponent(marker)+recount,
          			cache: false,
          			async: options.async != undefined ? options.async : true,
          			context: document.body,
          			success: function(data){
          				callback.success(data.space);
          			},
          		}, callback);		
          	};
          	
              dc.store.GetSpace2 = function(params){
                  var marker = '', prefix = '', async = true;
                  if(params.marker != undefined){
                      marker = params.marker;
                  }
                  if(params.prefix != undefined){
                      prefix = params.prefix;
                  }
                  if(params.async != undefined){
                      async = params.async;
                  }
          
                  return dc.ajax2({
                      url: "/duradmin/spaces/space", 
                      data: "storeId="+params.storeId+
                            "&spaceId="+encodeURIComponent(params.spaceId)+
                            "&prefix="+encodeURIComponent(prefix)+
                            "&marker="+encodeURIComponent(marker),
                      cache: false,
                      async: async,
                  });       
              };
          	
              dc.store.UpdateSpaceHlsStreaming = function(storeId, spaceId, /*bool*/enable){
                  var jqxhr = dc.ajax2({
                      url: "/duradmin/spaces/mediastreamer/hls?storeId="+storeId+"&spaceId="
                      + encodeURIComponent(spaceId)
                      + "&enable=" + enable,
                      type: "post",
                      cache: false,
                  }).fail(function(){
                      dc.displayErrorDialog(jqxhr);
                  });
                  return jqxhr;
              };
              
               
          	/**
          	 * @param Object space
          	 * @param Object callback The callback must implement success and failure methods. options begin method is supported.
          	 */
          	dc.store.DeleteSpace = function(space, callback){
          		return dc.ajax({
          			url: "/duradmin/spaces/space/delete", 
          			data: "storeId="+space.storeId+"&spaceId="+encodeURIComponent(space.spaceId),
          			type: "POST",
          			success: callback.success,
          		    failure: callback.failure,
          		}, callback);
          	};
          
          	/**
          	 * @param String space  space
          	 * @param bool publicFlag  indicates whether the space should be created with public access enabled. 
          	 * @param Object callback The callback must implement success and failure methods. options begin method is supported.
          	 */
          	dc.store.AddSpace = function(space, publicFlag, callback){
          		dc.ajax(
          			{
          				url: "/duradmin/spaces/space", 
          				data: "storeId="+space.storeId+"&spaceId="+encodeURIComponent(space.spaceId)+"&publicFlag="+publicFlag,
          				type: "POST",
          				success: function(data){
          					callback.success(data.space)
          				},
          			    failure:callback.failure,
          			},callback);
          	};
          
          	/**
          	 * Returns a list of spaces
          	 * @param String storeProviderId The id of the store provider
          	 * @param boolean writeableOnly Indicates that only spaces writeable 
          	 *                              for the current caller should be returned
          	 * @param Object callback
          	 * @option Function success(spaces) a handler for an array of spaces
          	 * @option Function failure(info) a handler that returns failure info 
          	 */
          	dc.store.GetSpaces = function(storeProviderId, writeableOnly, callback, async){
          		dc.ajax({ 
          				url: "/duradmin/spaces/json", 
          				data: "storeId="+storeProviderId+"&writeableOnly="+writeableOnly,
          				cache: false,
          				async: (async != undefined ? async : true),
          				success: function(data){
          					callback.success(data.spaces);
          				},
          				failure:callback.failure,
          		},callback);
          		
          	};
          	
          	/**
          	 * params: storeProviderId, writeableOnly, async
          	 */
              dc.store.GetSpaces2 = function(params){
                  var writeableOnly = false,
                      async = true;
                  
                  if(params.writeableOnly){
                      writeableOnly = params.writeableOnly;
                  }
          
                  if(params.async){
                      async = params.async;
                  }
          
                  return dc.ajax2({ 
                          url: "/duradmin/spaces/json", 
                          data: "storeId="+params.storeId+"&writeableOnly="+writeableOnly,
                          cache: false,
                          async: (async != undefined ? async : true),
                  });
                  
              };
          	
          	/**
          	 * returns contentItem details
          	 */
          	dc.store.GetContentItem = function(storeProviderId, spaceId, contentItemId, callback){
          		return dc.ajax({
          				url: "/duradmin/spaces/content",
          				data: "storeId="+storeProviderId+"&spaceId="+encodeURIComponent(spaceId)+"&contentId="+encodeURIComponent(contentItemId),
                          cache: false,
          				success: function(data){
          					callback.success(data.contentItem);
          			    },
          			    failure: callback.failure,
          		},callback);
          
          	};
          	
          	/**
          	 * @param Object contentItem
          	 * @param Object callback The callback must implement success and failure methods. optional begin method is supported.
          	 */
          	dc.store.DeleteContentItem = function(contentItem, callback){
          		dc.ajax({
          			url: "/duradmin/spaces/content/delete", 
          			data: "storeId="+contentItem.storeId+"&spaceId="+encodeURIComponent(contentItem.spaceId)+"&contentId="+encodeURIComponent(contentItem.contentId),
          			type: "POST",
          			success: callback.success,
          		    failure: callback.failure,
          		},callback);
          	};
          
          	dc.store._appendNVPair = function(name, value){
          	    return "&"+name+"="+encodeURIComponent(value);
          	};
          
          	/**
               * @param Object contentItem
               * @param Object callback The callback must implement success and failure methods. optional begin method is supported.
               */
              dc.store.copyContentItem = function(storeId, spaceId, contentId, destStoreId, destSpaceId, destContentId, deleteOriginal, callback){
                  var anvp = dc.store._appendNVPair;
                  return dc.ajax({
                                  url: "/duradmin/spaces/content/copy", 
                                  data: "".concat(
                                        anvp("deleteOriginal", deleteOriginal),
                                        anvp("storeId", storeId),
                                        anvp("spaceId", spaceId),
                                        anvp("contentId", contentId),
                                        anvp("destStoreId", destStoreId),
                                        anvp("destSpaceId", destSpaceId),
                                        anvp("destContentId", destContentId)
                                      ),
                                  type: "POST",
                                  success: function(result){
                                      callback.success(result.contentItem);
                                  }
                              },callback);
              };
          
          	
          	/**
          	 * @param Object serialized form data
          	 * @param Object callback The callback must implement success and failure methods. optional begin method is supported.
          	 */
          	dc.store.UpdateContentItemMimetype = function(data, callback){
          		dc.ajax({
          			url: "/duradmin/spaces/content/change-mimetype", 
          			data: data,
          			type: "POST",
          			success: function(data,xhr){
          				if(data.contentItem != undefined){
          					callback.success(data.contentItem);
          				}else{
          					this.failure(data,xhr);
          				}
          			},
          		    failure: callback.failure,
          		},callback);
          	};
          
          	/**
          	 * Adds a content item.  
          	 * @param Object/String a reference to a form dom node or the form's id
          	 * @param Object future an object implementing a success and failure method.
          	 */
          	dc.store.AddContentItem = function(form, future){
          
                  $(form).ajaxSubmit({
          			iframe: true,
          			dataType: 'json',
          			success: function(){
          				dc.checkSession();
          				future.success(data);
          		    },
          		    error: function(xhr, status, errorThrown){
          		    	future.failure(status,xhr);
          		    },
          		});
          	};
          	
          	/**
          	 * checks if the content item already exists
          	 * @param spaceId
          	 * @param contentId
          	 * @param storeId 
          	 * 
          	 */
          	dc.store.CheckIfContentItemExists = function(contentItem, callback){
          		dc.store.GetContentItem(contentItem.storeId,contentItem.spaceId,contentItem.contentId,{
          			begin: function(){
          			},
          			
          			failure: function(text){
          				callback.success(false);
          			},
          
          			success: function(contentItem){
          				callback.success(contentItem != undefined);
          			},
          		});
          	};
          	
          	/**
          	 * 
          	 */
          	dc.store.formatJ2kViewerURL = function(/*string*/j2kViewerBaseURL, /*object*/contentItem, /*boolean*/ openSpace){
          		var contentUrl = contentItem.durastoreURL;
                  if(!openSpace){
                      contentUrl = contentUrl.replace("http://", "https://");}
                  return j2kViewerBaseURL + "/viewer.html?rft_id=" + encodeURIComponent(contentUrl);
          	};
          
              /**
               * Retrieves an HLS streaming URL for a given content item in a given space.
               * The URL will be either open or secure, depending on the streaming type.
               */
              dc.store.GetHlsUrl = function(contentItem, hlsStreamingType, callback){
                  return dc.ajax({
                      url: "/duradmin/spaces/content/hls-url",
                      data: "storeId="+contentItem.storeId+
                      "&spaceId="+encodeURIComponent(contentItem.spaceId)+
                      "&contentId="+encodeURIComponent(contentItem.contentId)+
                      "&hlsStreamingType="+hlsStreamingType,
                      cache: false,
                      success: function(data){
                          callback.success(data);
                      },
                      failure: function(data){
                          callback.failure(data);
                      }
                  },callback);
              };
          	
          	/**
          	 * 
          	 */
          	dc.store.formatThumbnail = function(/*object*/contentItem, /*int*/ size, /*optional - string*/j2kViewerBaseURL, /*boolean*/ openSpace ){
                  var contentUrl = contentItem.durastoreURL;
                  if(!openSpace)
                      contentUrl = contentUrl.replace("http://", "https://");
                  return j2kViewerBaseURL+
              			"/resolver?url_ver=Z39.88-2004&rft_id="+encodeURIComponent(contentUrl)+"&" +
                          "svc_id=info:lanl-repo/svc/getRegion&svc_val_fmt=info:ofi/fmt:kev:mtx:jpeg2000&" +
                          "svc.format=image/png&svc.level="+size+"&svc.rotate=0&svc.region=0,0,500,500";
              };
          
          
          	var GENERIC_THUMBNAIL_PREFIXES = ["image", "video", "text", "pdf"];
          	
          	/**
          	 * 
          	 */
              dc.store.formatGenericThumbnail = function(/*object*/contentItem){
                  var mimetype = contentItem.properties.mimetype;
              	var gtf,i;
              	for(i in GENERIC_THUMBNAIL_PREFIXES){
              		gtf = GENERIC_THUMBNAIL_PREFIXES[i];
              		if(mimetype.indexOf(gtf) == 0){
              			return "/duradmin/images/generic-thumb-" + gtf + ".png";
              		}
              	}
              	return "/duradmin/images/generic-thumb-other.png";
              };
              
              /**
               * 
               */
          	dc.store.formatDownloadURL = function(/*object*/contentItem, /*boolean*/ asAttachment){
          		if(asAttachment == undefined) asAttachment = true;
          		return "/duradmin/download/contentItem?spaceId=" +  encodeURIComponent(contentItem.spaceId) +
          			   "&contentId=" + encodeURIComponent(contentItem.contentId) + "&storeID=" + contentItem.storeId +
          			   "&attachment=" + asAttachment;
          	};	
          
          	/**
          	 * @param storeId
          	 * @param spaceId
          	 */
              dc.store.GetUnassignedSpaceAcls = function(storeId,spaceId, callback){
                  dc.ajax({
                      url: "/duradmin/spaces/acls/unassignedAcls?storeId="+storeId+"&spaceId="+spaceId, 
                      async: false,
                      cache: false,
                      success: function(data){
                          callback.success(data.acls);
                      },
                  }, callback);
              };
              
              /**
               * @param storeId
               * @param spaceId
               */
              dc.store.GetSpaceAcls = function(storeId,spaceId, callback){
                  dc.ajax({
                      url: "/duradmin/spaces/acls?storeId="+storeId+"&spaceId="+spaceId, 
                      async: false,
                      cache: false,
                      success: function(data){
                          callback.success(data.acls);
                      },
                  }, callback);
              };
              
              /**
               * @formData is serialized form data containing the following required fields:
               *             storeId 
               *             spaceId
               *           and one or more of the following non required fields:
               *             read (users/groups to give read access to)
               *             write (users/groups to give write access to)
               * @param add - optional parameter. If value is set to true the acls in the form
               *               will be added to the existing space acls rather than replacing them.              
               *             
               */
              dc.store.UpdateSpaceAcls = function(/*serialized form data*/formData, /*boolean*/ add, callback){
                  dc.ajax({
                      url: "/duradmin/spaces/acls?action="+(add ? "add":""), 
                      async: true,
                      data: formData,
                      type: "post",
                      success: function(data){
                          callback.success(data.acls);
                      },
                  });
              };
              
              
             /**
              * @param storeId
              * @param spaceId (optional)
              */
              dc.store.GetStorageStatsTimeline = function(storeId,spaceId, start, end){
          
                var url =  "/duradmin/storagestats/timeseries?storeId="+storeId;
                if(spaceId){
                  url = url + "&spaceId="+spaceId;
                }
          
                if(start){
                  url = url + "&start="+start.getTime();
                }
          
                if(end){
                  url = url + "&end="+end.getTime();
                }
          
                return dc.ajax2({
                      url: url, 
                      dataType: 'json',
                      async: false,
                      cache: false});
              };
            
              dc.store.GetStorageStatsSnapshot = function(storeId,date){
                var url =  "/duradmin/storagestats/snapshot-by-day?storeId="+storeId;
                url = url + "&date="+date.getTime();
                  return dc.ajax2({
                      url: url, 
                      dataType: 'json',
                      async: false,
                      cache: false});
              };
          
          
              
              dc.store.CreateSnapshot = function(/*serialized form data*/formData){
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshot", 
                      async: true,
                      dataType: 'json',
                      data: formData,
                      type: "post",
                  });
              };
          
              dc.store.RestoreSnapshot = function(storeId, snapshotId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/restores?storeId="+storeId+"&snapshotId="+snapshotId, 
                      async: true,
                      dataType: 'json',
                      type: "post",
                  });
              };
          
              dc.store.RequestRestoreSnapshot = function(storeId, snapshotId){
                return dc.ajax2({
                    url: "/duradmin/spaces/restores/request?storeId="+storeId+"&snapshotId="+snapshotId, 
                    async: true,
                    dataType: 'json',
                    type: "post",
                });
            };
          
              dc.store.GetSnapshots = function(storeId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshots/" + storeId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
          
              dc.store.GetSnapshotTotals = function(storeId, status) {
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshots/totals/" + storeId + "?status=" + status,
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
          
              dc.store.GetSnapshot = function(params){
                  
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshots/" + params.storeId + "/" + params.spaceId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
              
              dc.store.GetSnapshotRestoreSpaceId = function(params){
                return dc.ajax2({
                    url: "/duradmin/spaces/snapshots/" + params.storeId + "/" + params.snapshotId + "/restore-space-id", 
                    async: true,
                    dataType: 'json',
                    type: "get",
                });
            };
              
             
              dc.store.GetRestoreBySnapshot = function(storeId,snapshotId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/restores/"+storeId+"/by-snapshot/" + snapshotId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
              
              dc.store.GetRestore = function(storeId,restoreId){
                  return dc.ajax2({
                      url: "/duradmin/spaces/restores/"+storeId+"/"+restoreId, 
                      async: true,
                      dataType: 'json',
                      type: "get",
                  });
              };
                  
              
              
              dc.store.GetSnapshotProperties = function(storeId, spaceId){
                  
                  return dc.ajax2({
                      url: "/duradmin/spaces/snapshot?storeId="+ storeId + "&spaceId="+spaceId, 
                      dataType: 'json',
                      async: true,
                      type: "get",
                  });
              };
          
              dc.store.GetSnapshotContent = function(storeId, snapshotId, page, prefix){
                  if(!page){
                      page = 0;
                  }
                  return dc.ajax2({
                      url : "/duradmin/spaces/snapshots/" + storeId + "/" + snapshotId
                              + "/content?page=" + page + "&prefix="
                              + prefix,
                      dataType : 'json',
                      async : true,
                      type : "get",
                  });
              };
              
              dc.store.GetSnapshotHistory = function(storeId, snapshotId, page){
                  if(!page){
                      page = 0;
                  }
                  
                  return dc.ajax2({
                      url : dc.store.formatSnapshotHistoryUrl(storeId, snapshotId, page, "false"),
                      dataType : 'json',
                      async : true,
                      type : "get",
                  });
              };
              
              dc.store.formatSnapshotHistoryUrl = function(storeId, snapshotId, page, attachment) {
                return "/duradmin/spaces/snapshots/" + storeId + "/" + snapshotId
                + "/history?page=" + page + "&attachment=" + attachment;
              };
          
          })();
          
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        5. GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.dc.common.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (381 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.dc.common.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 17903
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"17903-1574428024000"
          Last-Modified: Fri, 22 Nov 2019 13:07:04 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (17903 bytes)
          /*
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           *
           * @author "Daniel Bernstein (dbernstein@duraspace.org)"
           */
          
          var dc;
          
          $(function(){
          	(function(){
          		///////////////////////////////////////////////////////////////////////
          		////duracloud js utils
          		///////////////////////////////////////////////////////////////////////
          		if(dc == undefined){
          			dc = {};
          		}
          
          
          		dc.log = function(message){
          			if(window.console){
          				console.log(message);
          			}
          		};
          
          		dc.debug = function(message){
          			if(window.console){
          				if(window.opera){
          					console.log(message);
          				}else{
          				    if(console.debug){
          	                    console.debug(message);
          				    }else{
          				        console.log(message);
          				    }
          				}
          			}
          		};
          
          	    dc.logXhr = function(xhr, message){
                     dc.error("status="+xhr.status + "; statusText="+xhr.statusText);
          	    };
          
          		dc.error = function(message){
          			if(window.console){
          				if(window.opera){
          					console.log(message);
          				}else{
          					console.error(message);
          				}
          			}
          		};
          
              dc.checkSession = function(data){
                if(data != undefined && data != null){
                  if(data.responseText){
                    data = data.responseText;
                  }
                  if(data.toString().indexOf("loginForm") > -1){
                    alert("Your session has timed out.");
                    window.location.reload();
                  }
                }
              };
          
          		dc.displayErrorDialog = function(xhr, textStatus, errorThrown, showStackTrace){
          			var errorText = xhr.responseText;
          
          
          			if(!textStatus){
          			    textStatus = "An unexpected error occurred:";
          			}
          
          			if(showStackTrace == undefined || showStackTrace == null){
          			  showStackTrace = true;
          			}
          
          			try{
          				var response = $.parseJSON(errorText);
          				errorText = "cause: " + response['exception.message'];
          				errorText += "; stacktrace: " + response['exception.stacktrace'];
          			}catch(error){
          
          			}
          
                dc.error("error: " +
                         errorThrown +
                         "; response=" +
                         errorText);
          
          	     var options = {
          	                    autoOpen: true,
          	                    show: 'fade',
          	                    hide: 'fade',
          	                    width:500,
          	                    resizable: true,
          	                    closeOnEscape:true,
          	                    modal: true,
          	                    buttons: {
          	                      "Close": function(){
          	                        $(this).dialog("close");
          	                        errorDialog.empty();
          	                      },
          	                    },
          	                  };
          
          
          			var errorDialog = $.fn.create("div");
          
          			$(document).append(errorDialog);
          			errorDialog.append("<h2>"+textStatus+"</h2>");
          
                if(showStackTrace){
          
                  errorDialog.append("<div><button>Show Details</button>" +
                                     "<div class='error-detail' style='overflow:auto;height:200px;display:none'>" +
                                     "<pre>"+errorText+"</pre></div>");
          
                  errorDialog.find("button").click(function(){
                    errorDialog.find(".error-detail").show();
                  });
          
                  options = $.extend(options, {
                    height: 350
                  });
                }
          
          
          			errorDialog.dialog(options);
          		};
          
          
          		dc.ajax2 = function(settings){
          		    return $.ajax(settings)
                            .error(function(data){
                              dc.checkSession(data);
                            })
                            .done(function(data) {
                              dc.checkSession(data);
                            });
          
          		};
          
          		dc.ajax = function(innerCallback, outerCallback){
          			var callback = $.extend(
          					true,
          					{},
          					innerCallback,
          					{
          						success: function(data, status, xhr){
          							dc.checkSession(data);
          							if(innerCallback.success != undefined){
          								innerCallback.success(data, status, xhr);
          							}else{
          								if(outerCallback != undefined
          										&& outerCallback.success != undefined){
          									outerCallback.success(data, status, xhr);
          								}
          							}
          						},
          						error: function(xhr, textStatus, errorThrown){
          							dc.error(xhr.responseText);
          							if(innerCallback.failure != undefined){
          								innerCallback.failure(textStatus, xhr, errorThrown);
          							}else if(outerCallback != undefined
          										&& outerCallback.failure != undefined){
          									outerCallback.failure(textStatus, xhr, errorThrown);
          							}else{
          								//default error handler
          								dc.done();
          								dc.displayErrorDialog(xhr, textStatus, errorThrown);
          							}
          						},
          
          						begin: (innerCallback.begin != undefined ? innerCallback.begin :
          								(outerCallback != undefined && outerCallback.begin != undefined ? outerCallback.begin : undefined)),
          					}
          			);
          
          			if(callback.begin != undefined){
          				callback.begin();
          			}
          
          			return $.ajax(callback);
          		};
          		/**
          		 * Create a cookie with the given name and value and other optional parameters.
          		 *
          		 * @example dc.cookie('the_cookie', 'the_value');
          		 * @desc Set the value of a cookie.
          		 * @example dc.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
          		 * @desc Create a cookie with all available options.
          		 * @example dc.cookie('the_cookie', 'the_value');
          		 * @desc Create a session cookie.
          		 * @example dc.cookie('the_cookie', null);
          		 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
          		 *       used when the cookie was set.
          		 *
          		 * @param String name The name of the cookie.
          		 * @param String value The value of the cookie.
          		 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
          		 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
          		 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
          		 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
          		 *                             when the the browser exits.
          		 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
          		 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
          		 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
          		 *                        require a secure protocol (like HTTPS).
          		 * @author Klaus Hartl/klaus.hartl@stilbuero.de - modified by Daniel Bernstein
          		 */
          		dc.cookie = function(name, value, options) {
          		    if (typeof value != 'undefined') { // name and value given, set cookie
          		        options = options || {};
          		        if (value === null) {
          		            value = '';
          		            options.expires = -1;
          		        }
          		        var expires = '';
          		        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
          		            var date;
          		            if (typeof options.expires == 'number') {
          		                date = new Date();
          		                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
          		            } else {
          		                date = options.expires;
          		            }
          		            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
          		        }
          		        // CAUTION: Needed to parenthesize options.path and options.domain
          		        // in the following expressions, otherwise they evaluate to undefined
          		        // in the packed version for some reason...
          		        var path = options.path ? '; path=' + (options.path) : '';
          		        var domain = options.domain ? '; domain=' + (options.domain) : '';
          		        var secure = options.secure ? '; secure' : '';
          		        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
          		    } else { // only name given, get cookie
          		        var cookieValue = null;
          		        if (document.cookie && document.cookie != '') {
          		            var cookies = document.cookie.split(';');
          		            for (var i = 0; i < cookies.length; i++) {
          		                var cookie = jQuery.trim(cookies[i]);
          		                // Does this cookie string begin with the name we want?
          		                if (cookie.substring(0, name.length + 1) == (name + '=')) {
          		                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          		                    break;
          		                }
          		            }
          		        }
          		        return cookieValue;
          		    }
          		};
          
          		dc.createTable = function(data, /*optional: array*/ columnDefs){
          			var table, body, row, i,j;
          			table = $.fn.create("table");
          			if(columnDefs){
          				row = $.fn.create("tr");
          				$.each(columnDefs, function(x,item){
          					var h = $.fn.create("th").html(item.name);
          					if(item.cssClass){
          						//h.addClass(item.cssClass);
          					}
          					row.append(h);
          				});
          				table.append($.fn.create("thead").append(row));
          			}
          
          			body = $.fn.create("tbody");
          			table.append(body);
          
          			for(i = 0; i < data.length; i++){
          				row = $.fn.create("tr");
          				$(body).append(row);
          				for(j = 0; j < data[i].length; j++){
          					var value = data[i][j],
          							cell = $.fn.create("td");
          
          					$(row).append(cell);
          
          					if(columnDefs && columnDefs[j]){
          						if(columnDefs[j].formatter){
          							value = columnDefs[j].formatter(value);
          						}
          
          						if(columnDefs[j].cssClass){
          							cell.addClass(columnDefs[j].cssClass);
          						}
          					}
          					cell.append(value);
          				}
          			}
          			return table;
          		};
          
          		dc.getMimetypeImageClass = function(mimetype){
          		var mtc = "";
          		if(mimetype.indexOf("audio") > -1){
          			mtc = "audio";
          		}else if(mimetype.indexOf("image") > -1){
          			mtc ="image";
          		}else if(mimetype.indexOf("video") > -1){
          			mtc = "video";
          		}else if(mimetype.indexOf("xml") > -1){
          			mtc = "xml";
          		}else if(mimetype.indexOf("zip") > -1){
          			mtc = "compression";
          		}else{
          			mtc = "generic";
          		}
          		return "mime-type-" + mtc;
          
          		};
          
          		var spNameMap = {};
          		spNameMap["AMAZON_S3"] = "Amazon S3";
          		spNameMap["AMAZON_GLACIER"] = "Amazon Glacier";
                          spNameMap["SWIFT_S3"] = "Swift S3";
          		spNameMap["CHRONOPOLIS"] = "Chronopolis";
          		spNameMap["IRODS"] = "iRODS";
          		dc.STORAGE_PROVIDER_KEY_MAP = spNameMap;
          
          
          		dc.formatGB = function(value, decimalplaces, showUnits){
          			if(!decimalplaces){
          				decimalplaces = 0;
          			}
          
          			if(showUnits == undefined){
          				showUnits = true;
          			}
          
          			value = new Number(value/(1000*1000*1000));
          			value =  value.toFixed(parseInt(decimalplaces));
          
          			if(showUnits){
          				return value +"GB";
          			}else{
          				return value;
          			}
          		};
          
          		dc.busy = function(message, options){
          			var d =
          			   $("#busy-dialog");
          			var modal = false;
          			var buttons = undefined;
          
          			if(options != undefined){
          				if(options.modal != undefined){
          					modal = options.modal;
          				}
          
          				if(options.buttons != undefined){
          					buttons = options.buttons;
          				}
          			}
          
          			var dOptions = {
          					autoOpen: false,
          					show: 'fade',
          					hide: 'fade',
          					resizable: false,
          					height: 100,
          					closeOnEscape:false,
          					modal: modal != undefined ? modal : false,
          					width:300,
          					close: function() {
          
          					},
          
          					open: function(e){
          					},
          			};
          
          			if(buttons != undefined){
          				dOptions.buttons = buttons;
          			}
          
          			d.dialog(dOptions);
          
          		   $("#busy-dialog-title").html(message);
          
          		   if(!d.dialog("isOpen")){
          		       d.dialog("open");
          		   }
          		};
          
          		dc.done = function(message){
          			$("#busy-dialog").dialog("close");
          
          			if(message != undefined){
          				var d = $("#message-dialog");
          				d.dialog({
          					autoOpen: false,
          					show: 'fade',
          					hide: 'fade',
          					resizable: false,
          					height: 100,
          					closeOnEscape:true,
          					modal: false,
          					width:300,
          					buttons: {
          						"Close" : function(){
          							$(this).dialog('close');
          						 },
          					},
          					close: function() {},
          					open: function(e){},
          				});
          
          			   $("#message-dialog-title").html(message);
          			   d.dialog("open");
          			}
          		};
          
          
          		dc.confirm = function(message,evt){
          			if(!confirm(message)){
          				if(evt != undefined){
          					evt.stopPropagation();
          					evt.preventDefault();
          				}
          				return false;
          			};
          
          			return true;
          		};
          
          
                  dc.extractStoreId = function(path){
                      var index = path.indexOf("?storeId=");
                      if(index > 0){
                          return path.substring(index+9);
                      }else{
                          return null;
                      }
                  };
          
          	    dc.extractSpaceId = function(path){
          	        var index = path.indexOf("/");
          	        return path.substring(0, index);
          	    };
          
          	    dc.extractContentId = function(path){
          	        var index = path.indexOf("/");
          	        var qsIndex = path.indexOf("?");
          	        return path.substring(index+1, (qsIndex > 0 ? qsIndex : path.length));
          	    };
          
          	    dc.reportOverlayOnClick = function(link, storeId, spaceId){
                      var params = "&spaceId=" + spaceId;
                      if(storeId){
                          params+="&storeId="+storeId;
                      }
          
                      var prefix = "/duradmin/servicesreport";
          
                      var fileInfoUrl = prefix + "/info?" + params;
          
                      var jqxhr = $.getJSON(fileInfoUrl, function(data){
                          var size = new Number(data.fileInfo.size);
                          if(size > (1024*1000)){
                              link.attr("href", prefix + "/raw?attachment=true&" + params);
                          }else{
                              var url = prefix + "/htmltable?" + params;
                              link.attr("href", url)
                                  .attr("title","View Bit Integrity Report")
                                  .fancybox({type: 'iframe',
                                             width: 800,
                                             scrolling: 'auto',
                                             titleShow: false,
                                          });
                          }
                      });
          	    };
          
          		/**
          		 * checks the progress of a remote task and notifies caller of results.
          		 */
          		var DEFAULT_POLL_INTERVAL = 5000;
          
          		dc.checkProgress = function(url, key, callback){
          
          			if(callback.count == undefined){
          				callback.count = 0;
          			}
          
          			var updater = function(progressCallback, data){
          				if(data.error){
          					_error(data.message);
          					progressCallback.failure(message);
          					return;
          				}
          
          				progressCallback.update(data);
          				if(data.task != undefined){
          					var state = data.task.properties.state;
          
          					if(state == 'running' || state == 'initialized'){
          						setTimeout(function(){ dc.checkProgress(url,key, progressCallback); }, DEFAULT_POLL_INTERVAL);
          					}else if(state == 'success'){
          						if(progressCallback.success != undefined){
          							progressCallback.success(data);
          						}
          					}else if(state == 'cancelled'){
          						if(progressCallback.cancel != undefined){
          							progressCallback.cancel();
          						}
          					}else{
          						if(progressCallback.failure != undefined){
          							progressCallback.failure();
          						}
          					}
          				}
          			};
          
          			dc.ajax({ url: url,
          				cache: false,
          				type: "GET",
          				success: function(data){
          					//ajax response gets set here
          					updater(callback, data);
          			    },
          			    failure: function(textStatus){
          			    	alert("updater failed: " + textStatus);
          			    },
          			});
          		};
          
                  /**
                  * Login function
                  *
                  * @return jqXHR Jquery XmlHttpRequest object.
                  */
                  dc.login = function(/* jquery object */form) {
                      var message = $("#msg-error");
                      var feedback = $("#feedback");
                      return $.ajax({
                          type : "POST",
                          url : form.attr("action"),
                          data : form.serialize(),
                          cache : false,
                          beforeSend : function() {
                              message.makeHidden();
                              feedback.fadeIn();
                          },
                          complete : function() {
                              feedback.fadeOut();
                          },
                          success : function(data, textStatus, jqXHR) {
                              try {
                                  dc.debug("data=" + data);
                                  if (data.indexOf(form.attr("id")) > 0) {
                                      message.makeVisible();
                                      message.fadeIn();
                                  } else {
                                      location.reload(true);
                                  }
                              } catch (err) {
                                  dc.error(err);
                                  dc.displayErrorDialog(jqXHR, textStatus,
                                          "An unexpected error occurred: " + err);
                              }
                          },
                          error : function(jqXHR, text, errorThrown) {
                              dc.displayErrorDialog(jqXHR, text, errorThrown);
                          },
                      });
                  };
          
          
                  dc.formatBytes = function(bytes, showBytes){
                      var val = null;
                      bytes = new Number(bytes);
                      var bytesValue = bytes + " bytes";
          
                      if(bytes < 1000){
                          return bytesValue;
                      }else if(bytes < 1000*1000){
                         val = (bytes/1000).toFixed(1) + " KB";
                      }else if(bytes < 1000*1000*1000){
                          val = (bytes/(1000*1000)).toFixed(1) + " MB";
                      }else{
                          val = (bytes/(1000*1000*1000)).toFixed(1) + " GB";
                      }
          
                      if(showBytes){
                          val += " (" + bytesValue + ")";
                      }
                      return val;
                  };
          
          
                  dc.hexEncode = function(val) {
                    var hex, i;
          
                    var result = "";
                    for (i = 0; i < val.length; i++) {
                      hex = val.charCodeAt(i).toString(16);
                      result += ("000" + hex).slice(-4);
                    }
          
                    return result
                  };
          
                dc.hexDecode = function(val) {
                  var j;
                  var hexes = val.match(/.{1,4}/g) || [];
                  var back = "";
                  for (j = 0; j < hexes.length; j++) {
                    back += String.fromCharCode(parseInt(hexes[j], 16));
                  }
          
                  return back;
                };
          
          	})();
          });
          
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        6. GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.fn.ext.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (378 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.fn.ext.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 5462
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"5462-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (5462 bytes)
          /*
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           * A collection of useful jquery extensions
           * @author "Daniel Bernstein (dbernstein@duraspace.org)"
           */
          
          
          $(function(){
          	(function(){
          		////////////////////////////////////////////////////////////////////
          		//jquery extensions
          		///////////////////////////////////////////////////////////////////
          	    $.fn.disable = function(/*boolean*/ val){
          	        if(!val){
          	           return $(this).removeAttr("disabled");
          	        }else{
          	           return $(this).attr("disabled", "disabled");
          	        }
          	    };
          	    
          	    /**
          		 * Similar to hide/show jquery functions but toggles the visibility css 
          		 * attribute instead of the display attribute.
          		 */
          		$.fn.makeVisible = function(isvisible) {
          			return $(this).css("visibility", (isvisible == undefined || isvisible) ? "visible":"hidden");
          		};
          		
          		$.fn.makeHidden = function() {
          			return $(this).makeVisible(false);
          		};
          
          		
          		/**
          		 * This finds the nearest ancestor of the specified class.  It is just like jQuery.closest(selector) except
          		 * that it includes the dom node your are calling the function on.
          		 */
          		$.fn.nearestOfClass = function(className){
          			var nearest = (this.hasClass(className)) ? this : this.closest("." + className);
          			return $(nearest);
          		};
          
          		
          		$.fn.toggleOpenClosed = function(){
          			$(this).nearestOfClass("button")
          					.toggleClass("dialog-open")
          					.toggleClass("dialog-closed");
          		};
          
          		/**
          		 * Shorthand for document.createElement
          		 * Returns the new element as a jQuery object.
          		 */
          		$.fn.create = function(tag){
          			return $(document.createElement(tag));
          			
          		};
          		
          		/**
          		 * Scrolls the specified dom element to the top of the 
          		 * viewport (which is the object on which you're calling this function)
          		 * if possible. If it can't scroll it to the top of the viewport it at 
          		 * least scrolls the container so that the element is in view.
          		 * @param DOM node or jquery object
          		 */
          		$.fn.scrollTo = function(element){
          			var top = $(element).offset().top;
          			this.animate({scrollTop: top}, {duration:"slow", easing:"swing", queue:true});
          		};
          
          		/**
          		 * Returns true if the element is in the viewport
          		 */
           		$.fn.isVisibleInViewPort = function() {
           		        var rect = this.get(0).getBoundingClientRect();
          
           		        return rect.bottom > 0 &&
           		            rect.right > 0 &&
           		            rect.left < (window.innerWidth || document. documentElement.clientWidth) /*or $(window).width() */ &&
           		            rect.top < (window.innerHeight || document. documentElement.clientHeight) /*or $(window).height() */;
           		}
          
          		/**
          		 * this method loads the children of the new contents
          		 * into the target after emptying the contents
          		 * with a fade in / fade out effect
          		 */
          		$.fn.replaceContents = function(/*the pane whose contents will be swapped in*/ newContents,  
          										/*the layout for the target*/ layoutOptions){
          			var target = this;
          			//$(target).fadeOut("fast", function(){
          				$(target).empty().prepend($(newContents).children());
          				//$(target).fadeIn("fast");
          				if(layoutOptions != null && layoutOptions != undefined){
          					$(target).layout(layoutOptions);
          				}
          			//});
          			return $(target);
          		};	
          
          		/**
          		 * Closes the dialog when the user clicks off of it.
          		 */
          		$.fn.closeOnLostFocus = function() { // on the open event
          		    // find the dialog element
          		    var dialogEl = this;        
          		    $(document).click(function (e) { // when anywhere in the doc is clicked
          		        var clickedOutside = true; // start searching assuming we clicked outside
          		        $(e.target).parents().andSelf().each(function () { // search parents and self
          		            // if the original dialog selector is the click's target or a parent of the target
          		            // we have not clicked outside the box
          		            if ($(this).first().attr("id") == $(dialogEl).attr("id")) {
          		                clickedOutside = false; // found
          		                return false; // stop searching
          		            }
          		        });
          		        if (clickedOutside) {
          		            $(dialogEl).dialog("close"); // close the dialog
          		            // unbind this listener, we're done with it
          		            $(document).unbind('click',arguments.callee); 
          		        }
          		    });
          		};
          		
          		
          		/**
          		 * Binds the enter keyup event to the specified function.
          		 */
          		$.fn.bindEnterKey = function(func) {
          			$(this).bind('keydown', function(e){
          			    if(e.keyCode==13){
          		        	func(e);
          			    }
          			});		
          			
          			return this;
          		};
          		
          		$.fn.busy = function(){
          		    $(".dc-busy",this).show("fast");
          		    return this;
          		};
          
          		$.fn.idle = function(){
                      $(".dc-busy",this).hide();
                      return this;
                  };
          
          
              $.fn.busySibling = function(text){
                var busy = $("<div class='dc-busy-holder'></div>");
                if(text){
                  busy.html(text);
                }
                
                busy.insertAfter($(this));
                busy.show("fast");
                return this;
              };
          
              $.fn.idleSibling = function(){
                $(this).siblings(".dc-busy-holder").hide("fast").remove();
                return this;
              };
          
              //adds in missing addBack function for plugins that depend on it (namely jquery dropdown)
              $.fn.addBack = function (selector) {
                return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
              };
                  
          	})();
          });
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        7. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.expandopanel.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (383 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.expandopanel.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 3230
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"3230-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (3230 bytes)
          /**
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           * @author Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///selectable list widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          
          /**
           * expando panel widget
           */
          $.widget("ui.expandopanel",{
          	/**
          	 * Default values go here
          	 */
          	options: {
          			open: true,
          			togglerClass: "dc-toggler",
          			togglerClassClose: "dc-toggler-close",
          			title: null,
          			headerClass: "segment-header",
          			contentClass: "segment-content",
          	},
          	
          	_header: null,
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		var options = this.options;
          		var togglerClass = options.togglerClass;
          		var clearFixClass = "clearfix";
          		
          		//add children if none are defined in html
          		while($(this.element).children().size() < 2){
          			$(this.element).append(document.createElement("div"));
          		};
          		
          		this._header = $(this.element).children().first();
          		var content = $(this.element).children().last();
          		var title = options.title;
          		
           		//set the title if not null
          		if(title != null){
          			this._header.html(title);
          		}
          		
          		//add toggle button
          		if($("."+togglerClass,this.element).size() == 0){
          			this._header.append("<a class='"+togglerClass+"'></a>");
          		}
          		
          		var toggler = this._header.children().first();
          		
          		//style the header
          		this._header.addClass(options.headerClass);
          		this._header.addClass(options.clearfix);
          		
          		
          		//add toggle to the header 
          		this._header.click(function(evt){
          			toggler.toggleClass(options.togglerClassClose);
          			content.slideToggle("fast");
          		});
          		
          		//style the content 
          		content.addClass(options.contentClass);
          		content.addClass(options.clearfix);
          
          		if(!options.open){
          			content.css("display", "none");
                      toggler.toggleClass(options.togglerClassClose);
          		}
          
          	},
          	
          	toggle: function(){
          	    $(this._header).trigger("click");
          	},
          	
          	getContent: function(){
          		return $(this.element).children().last();
          	},
          	
          	append: function(/*dom node*/ node){
          		this.getContent().append(node);
          	},
          });
          
          /**
           * Tabular Expando Panel: used for displaying lists of static properties
           */
          $.widget("ui.tabularexpandopanel", 
          	$.extend({}, $.ui.expandopanel.prototype, 
          		{  //extended definition 
          			_init: function(){ 
          				$.ui.expandopanel.prototype._init.call(this); //call super init first
          				//add the table if it is not null
          				var d = this.options.data;
          				this.setData(d);
          			}, 
          
          			setData: function(data){ 
          				var tableClass = "ui-tabularexpandopanel-table";
          				$("."+tableClass, this.element).remove();
          				if(data != null){
          					var table = dc.createTable(data, ["label", "value"]);
          					$(table).addClass(tableClass)
          					        .attr("role", "presentation");
          
          					this.append(table);
          				}
          
          			}, 
          
          			destroy: function(){ 
          				//tabular destroy here
          				$.ui.expandopanel.prototype.destroy.call(this); // call the original function 
          			}, 
          			
          			options: $.extend({}, $.ui.expandopanel.prototype.options, {
          				data: [],  //2 dimensional array
          			}),
          		}
          	)
          ); 
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        8. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.listdetailviewer.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (387 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.listdetailviewer.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 2185
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"2185-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (2185 bytes)
          /**
           * This jquery plugin combines a selectablelist with a "detail" pane.
           * created by Daniel Bernstein
           */
          $.widget("ui.listdetailviewer", 
          	{  
          		_init: function(){ 
          			var that = this;
          			var o = this.options;
          			//reference the selectablelist if it exists
          			var list = $("#"+o.selectableListId).first();
          			if(list == null || list == undefined){
          				list = $.fn.create("div").attr("id", o.selectableListId);
          				$(this.element).append(list);
          			}
          
          			var dt = $("#"+o.detailId).first();
          			if(dt == null || dt == undefined){
          				dt = $.fn.create("div").attr("id", o.detailId);
          				$(this.element).append(detail);
          			}
          			
          			
          			//initialize list
          			list.selectablelist({ selectable: false })
          				.bind("currentItemChanged", function(evt, state){
          					var currentItem = state.currentItem;
          					if(currentItem == null){
          						that._showNoSelection();
          					}else{
          						var data = currentItem.data;
          						if(data == null || data == undefined){
          							that._showNoSelection();
          						}else{
          							var detail = that._prepareDetail(data);
          							that._getDetail().replaceContents(detail,o.detailLayout);
          						}
          					}
          				});
          			
          		}, 
          		
          		destroy: function(){ 
          
          		}, 
          		
          		options: {
          				selectableListId: "selectable-list"
          			,	detailId:  "list-detail"
          			,   detailClass: "dc-detail"
          			,   detailPreparer: function(data){
          					 var that = this;
          					 var detail = $.fn.create("div");
          					 var proplist = $.fn.create("table");
          					 detail.append(proplist);
          					 for(i in data){
          						 proplist.append(
          							 $.fn.create("tr")
          							 	.append($.fn.create("td").html(i))
          							 	.append($.fn.create("td").html(data[i]))
          						 );
          					 }
          					 
          					 return detail;
          				}
          		},
          		
          		//default behavior removes the children
          		_showNoSelection: function(){
          			this._clearDetail();
          		},
          		
          		_clearDetail: function(){
          			 $("#"+this.options.detailId, this.element)
          				.children().remove();			
          			
          		},
          		
          		_getDetail: function(){
          			 return $("#"+this.options.detailId, this.element);
          		},
          		
          		
          		//load detail
          		//default behavior: iterator through members and write them to an table
          		_prepareDetail: function(data){
          			return this.options.detailPreparer(data);
          		},
          	}
          );
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        9. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.onoffswitch.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (382 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.onoffswitch.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 3055
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"3055-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (3055 bytes)
          /**
           * created by Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///on off switch  widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          $.widget("ui.onoffswitch",{
          	/**
          	 * Default values go here
          	 */
          	options: {
                initialState: "on"
          		, onStateClass: "on left"
          		, onIconClass: "unlock"
          		, offStateClass: "off right"
          		, offIconClass: "lock"
          		, onText: "On"
          		, offText: "Off"
          		, readOnly: false
          	},
          	
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		//clear the element state
          		$(that.element).html("");
          		var o = this.options;
          		var leftButtonOnState = this._createButton(o.onText, o.onStateClass, o.onIconClass, false, o.readOnly);
          		var rightButtonOnState = this._createButton(o.offText, o.offStateClass, o.offIconClass, true, o.readOnly);
          		var leftButtonOffState = this._createButton(o.onText, o.onStateClass, o.onIconClass, true, o.readOnly);
          		var rightButtonOffState = this._createButton(o.offText, o.offStateClass, o.offIconClass, false, o.readOnly);
          		
          		rightButtonOnState.click(function(evt){
          			evt.preventDefault();
          			that._fireOffEvent();
          		});
          		
          		var onState = $.fn.create("span")
          							.addClass("button-holder")
          							.addClass("button-holder-on")
          							.append(leftButtonOnState)
          							.append(rightButtonOnState);
          		
          		$(this.element).append(onState);
          
          
          		leftButtonOffState.click(function(evt){
          			evt.preventDefault();
          			that._fireOnEvent(evt);
          		});
          		var offState = $.fn.create("span")
          							.addClass("button-holder")
          							.addClass("button-holder-off")
          							.append(leftButtonOffState)
          							.append(rightButtonOffState);
          		$(this.element).append(offState);
          
          		
          		this._switch(o.initialState);
          	},
          	
          	_fireOnEvent: function(evt){
          		var that = this;
          		this.element.trigger("turnOn", {
          			success:function(evt){ 
          				that._switch("on")
          			},
          			
          			failure: function(evt){
          				alert("no turn on failure handler defined");
          			},
          		});
          	},
          
          	_fireOffEvent: function(){
          		var that = this;
          		this.element.trigger("turnOff", {
          			success:function(evt){ 
          				that._switch("off")
          			},
          			
          			failure: function(evt){
          				alert("no turn offfailure handler defined");
          			},
          		});
          	},
          
          	_switch: function(state){
          		$(".button-holder", this.element).css("display","none");
          
          		if(state =="on"){
          			$(".button-holder-on", this.element).css("display","inline-block");
          		}else{
          			$(".button-holder-off", this.element).css("display","inline-block");
          		}
          	},
          	
          	on: function(){
          		this._switch("on");
          		this._fireOnEvent();
          	},
          	
          	_createButton: function(text, stateClass, iconClass, clickable, readOnly)
          	{
          		var button;
          		var icon = $.fn.create("i")
          			.addClass("pre")
          			.addClass(iconClass);
          		if (clickable) {
          			button = $.fn.create("button");
          		} else {
          			button = $.fn.create("span");	
          		}
          		button
          			.addClass("switch")
          			.addClass(stateClass) // need to change to be "left" for on, "right" for off
          			.append(icon)
          			.append(text)
          		    .disable(readOnly);
          		return button;
          	}
          });
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        10. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (385 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 11271
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"11271-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (11271 bytes)
          /**
           * 
           * created by Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///selectable list widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          (function(){
          /**
           * Selectable list widget
           */
          $.widget("ui.selectablelist",{
          	
          	/**
          	 * Default values go here
          	 */
          	options: {
          	
          			itemClass: "dc-item"
          		,   selectable: true
          		,   clickable: true
          		,   itemActionClass: "dc-action-panel"
          			
          	},
          	
          	_currentItem: null,
          	_footer: null,
          	dataMap: new Array(),
          	
          	_restyleSiblings: function(siblings){
          		siblings.removeClass("dc-selected-list-item dc-checked-selected-list-item dc-checked-list-item");
          		siblings.find("input[type='checkbox']:checked").closest("." +this.options.itemClass).addClass("dc-checked-list-item");
          	},
          	
          	_styleItem:  function(target){
          		if(target != undefined && target != null){
          			var item = $(target).nearestOfClass(this.options.itemClass);
          			$(item).removeClass("dc-checked-selected-list-item dc-checked-list-item dc-selected-list-item");
          			var checked = $(item).find("input[type='checkbox']:checked").size() > 0;
          			$(item).addClass(checked ? "dc-checked-selected-list-item" : "dc-selected-list-item");
          			this._restyleSiblings(item.siblings());
          		}else{
          			this._restyleSiblings(this.element.children("."+this.options.itemClass));
          		}
          		
          	},
          
          	_getSelectedItems: function(){
          		var array =  new Array();
          		var items = this.element.find("."+this.options.itemClass).toArray();
          		$.each(items, function(i, e){
          			if($(e).find("input[type='checkbox']:checked").size() > 0){
          				array.push(e);
          			}
          		});
          
          		return array;
          	},
          	
          	getSelectedData: function(){
          		var that = this;
          		var selected = this._getSelectedItems();
          		var selectedData = new Array();
          		$.each(selected, function(i,selectedItem){
          			selectedData.push(that._getDataById($(selectedItem).attr("id")));
          		});
          		
          		return selectedData;
          	},
          	
          	_setCurrentItem: function(item){
              this._currentItem = {
                                   item:item, 
                                   data: this._getDataById($(item).attr("id")),
                                 };
          	},
          	
          	_fireCurrentItemChanged: function(item, notify){
          		
          		if(item != null){
          		  this._setCurrentItem(item);
          		}else{
          			this._currentItem = null;
          		}
          		
          		
          		$("input[type='checkbox']:checked",this.element).removeAttr("checked");
          		this._styleItem(item);
          		if(item){
          		    $(item).find("input[type='checkbox']")
          		           .not("[disabled]")
          		           .attr("checked",true);
          		}
          
                  var selectedItems = this._getSelectedItems();
          		
          		var fire = (notify == undefined || notify == null || notify == true);
          		if(fire){
          			this.element.trigger(
          				"currentItemChanged",
          				{	
          					currentItem:this._currentItem, 
          					selectedItems: selectedItems
          				}
          			);
          		}
          	},
          	
          	_fireSelectionChanged: function(){
          	  var selectedItems = this._getSelectedItems();
              
          		if(selectedItems.length == 0){
          		    this._fireCurrentItemChanged(null, false);
          		}else if(selectedItems.length == 1){
          		 this._currentItem = this._setCurrentItem(selectedItems[0]);
          		}
          		
          		var ci = this._currentItem;
              this._styleItem(ci != null && ci.item != null ? ci.item : null);
              
          		
          		this.element.trigger(
          			"selectionChanged", 
          			{
          				selectedItems: this._getSelectedItems(), 
          				currentItem: this._currentItem,
          			}
          		);
          	},
          
          	_fireItemRemoved: function(item, data){
          		this.element.trigger(
          		  "itemRemoved", 
          		  {
          		      item: item,
          		      data: data,
          		  }
          	    );
          	},
          
          
          
          	_itemSelectionStateChanged: function(target){
          		var item = $(target).closest("."+this.options.itemClass);
          		this._fireSelectionChanged(item);
          	},
          	
          	clear: function(notify){
          		this._currentItem = null;
          		this.element.children("."+this.options.itemClass).remove();	
                  this.element.children("."+this.options.itemClass + "-divider").remove(); 
          		this.dataMap = new Array();
          		this._fireCurrentItemChanged(null,notify);
          		$(this._footer).html('');
          	},
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		this.clear(false);
          
          		this._footer = $.fn.create("div").addClass("dc-selectablelist-footer").html("");
          		$(that.element).append(that._footer);
          		
          		//add item classes to all direct children
          		$(that.element).children("."+this.options.itemClass).each(function(i,c){
          			that._initItem(c);
          		});
          		
          		that.element.unbind().bind("selectionChanged", function(evt, state){
          			var selectionChanged = that.options.selectionChanged;
          			if(selectionChanged){
          				selectionChanged(evt,state);
          			}
          		});
          		
          	},
          	
          
              	addItem : function(item, 
              	                   data, 
              	                   selected, 
              	                   /* optional boolean */disabled, 
              	                   /*optional boolean*/noIndent, //suppresses indentation for non-selectable items.
              	                   /*optional String*/ dividerLabel //specifies label of the section 
              	                                                    //into which the item should be inserted.
              	                   ) {
              	var that = this;
                this.setFooter('');
                if(dividerLabel){
                  var dividers = [];
                  $("." + this.itemDividerClass(), this.element).each(function(i,e){
                      dividers.push(e);
                  });
                  
                  if(dividers.length > 0){
                    
                    $.each(dividers, function(i, div){
                      if($(div).html() == dividerLabel){
                         if(i == dividers.length-1){
                           that._footer.before(item);
                         }else{
                           $(dividers[i+1]).before(item);
                         }
                         
                         return false;
                      }
                    });
                  }else{
                    this._footer.before(item);
                  }
                
          
                  if (selected && this.options.selectable) {
                    $("input[type=checkbox]", item).attr("checked", true);
                  }
                  
                }else{
                    this._footer.before(item);
                }
          
                this._initItem(item, data, disabled, noIndent);
          
                return item;
              },
              
              itemDividerClass: function(){
                return this.options.itemClass+"-divider";
              },
          	
              addDivider: function(label){
                  this.setFooter('');
                  
                  var divider = $.fn.create("div").addClass(this.itemDividerClass());
                  divider.html(label);
                  this._footer.before(divider);
              },
          	
          	select: function(select){
          		var that = this;
          		that._select(select);
          		that._fireSelectionChanged();
          	},
          
              _select: function(select){
                  var that = this;
                  $("input[type=checkbox]",this.element).not("[disabled]").attr("checked",select);
              },
          
          	removeById: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		var data = this._removeDataById(elementId);
          		item.remove();
          		
          		if(this._currentItem){
          		    if($(this._currentItem.item).attr("id") == elementId){
          	            this._fireCurrentItemChanged(null);
          		    }
          		}
          		this._fireItemRemoved(item, data);
          	},
          
          	idExists: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		if(item){
          			return true;
          		}else{
          			return false;
          		}
          	},
          
          
          	_getDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_removeDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				this.dataMap.splice(i,1);
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_putData: function(id,data){
          		this.dataMap[this.dataMap.length] = { key: id, value: data};
          	},
          	
          	setCurrentItemById: function(id, notify){
          	    if(this._currentItem){
          	        if(this._currentItem.item.attr("id") == id){
          	            return;
          	        }
          	    }
          		this._fireCurrentItemChanged($("#"+id, this.element), notify);
          	},
          	
          	setFirstItemAsCurrent: function(){
          		 var first = this.element.children("."+this.options.itemClass).first();
          		 if(first != undefined && first !=null){
          			 this._fireCurrentItemChanged(first, true);
          		 }
          	},
          
          	lastItemData: function(){
          		 var last = this.lastItem();
          		 if(last != undefined && last != null){
          			 return this._getDataById($(last).attr("id"));
          		 }
          		 return null;
          	},
          	
          	lastItem: function(){
          		 return this.element.children("."+this.options.itemClass).last();
          	},
          
          	length: function(){
          		 return this.element.children("."+this.options.itemClass).size();
          	},
          
          	
          	currentItem:function(){
          		return this._currentItem;
          	},
          	
          	setFooter:function(footerContent){
          		this._footer.html('');
          		$(this._footer).append(footerContent);
          	},
          
          	_initItem : function(item, data, selectionDisabled, noIndent) {
                var that = this;
                var o = this.options;
                var itemClass = o.itemClass;
                var actionClass = o.itemActionClass;
                var checkbox;
                var checkboxHolder;
          
                if (selectionDisabled == undefined || selectionDisabled == null) {
                  selectionDisabled = false;
                }
          
                $(item).addClass(itemClass);
          
                if (this.options.selectable && !(selectionDisabled && noIndent)) {
                  var checkbox = $("<input type='checkbox'/>");
                  checkbox.attr("aria-labelledby", item.attr("id"));
                  //checkbox holder serves to create a clickable
                  //buffer zone around the checkbox in order to
                  //make it easier for the user to check.
                  var checkboxHolder = $("<span class='cb-holder'></span>");
                  checkboxHolder.append(checkbox);
                  $(item).prepend(checkboxHolder);
          
                  if (selectionDisabled != undefined) {
                    checkbox.disable(selectionDisabled);
                    if (selectionDisabled) {
                      checkbox.makeHidden();
                    } else {
                      checkboxHolder.click(function(evt) {
                        if (evt.target == this) {
                          if (checkbox.is(":checked")) {
                            checkbox.removeAttr("checked");
                          } else {
                            checkbox.attr("checked", "checked");
                          }
                          that._itemSelectionStateChanged(checkbox);
                        }
                        evt.stopPropagation();
                      });
                    }
                  }
          
                  $(item).children().first().change(function(evt) {
                    that._itemSelectionStateChanged(evt.target);
                    evt.stopPropagation();
                  });
                }
          
                $(item).children("div").last().addClass("float-r").addClass(actionClass);
          
                var clickHandler = function(evt) {
                  var item = $(evt.target).nearestOfClass(itemClass);
                  if ($(evt.target).attr("type") != "checkbox") {
          
                    if (that.options.clickable) {
                      if (that.options.selectable) {
                        that._select(false);
                        item.find(":checkbox").not("[disabled]").attr("checked", true);
                      }
          
                      that._fireCurrentItemChanged(item);
                    }
          
                    evt.stopPropagation();
                  }
                };
          
                //bind mouse action listeners
                $(item).find("." + actionClass).andSelf().click(clickHandler).dblclick(clickHandler).mouseover(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeVisible();
                }).mouseout(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeHidden();
                });
          
                //hide all actions to start
                $(item).find("." + actionClass).makeHidden();
          
                //add the data to the map
                that._putData($(item).attr("id"), data);
                return item;
              }
          });
          
          })();
          
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        11. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        12. GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (368 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 93868
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"93868-1329845124000"
          Last-Modified: Tue, 21 Feb 2012 17:25:24 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (93868 bytes)
          /*! jQuery v1.7.1 jquery.com | jquery.org/license */
          (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
          f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.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(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
          {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        13. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (397 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 37133
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"37133-1268175436000"
          Last-Modified: Tue, 09 Mar 2010 22:57:16 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (37133 bytes)
          /*
           * jQuery validation plug-in 1.7
           *
           * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
           * http://docs.jquery.com/Plugins/Validation
           *
           * Copyright (c) 2006 - 2008 Jörn Zaefferer
           *
           * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          $.extend($.fn, {
          	// http://docs.jquery.com/Plugins/Validation/validate
          	validate: function( options ) {
          
          		// if nothing is selected, return nothing; can't chain anyway
          		if (!this.length) {
          			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
          			return;
          		}
          
          		// check if a validator for this form was already created
          		var validator = $.data(this[0], 'validator');
          		if ( validator ) {
          			return validator;
          		}
          		
          		validator = new $.validator( options, this[0] );
          		$.data(this[0], 'validator', validator); 
          		
          		if ( validator.settings.onsubmit ) {
          		
          			// allow suppresing validation by adding a cancel class to the submit button
          			this.find("input, button").filter(".cancel").click(function() {
          				validator.cancelSubmit = true;
          			});
          			
          			// when a submitHandler is used, capture the submitting button
          			if (validator.settings.submitHandler) {
          				this.find("input, button").filter(":submit").click(function() {
          					validator.submitButton = this;
          				});
          			}
          		
          			// validate the form on submit
          			this.submit( function( event ) {
          				if ( validator.settings.debug )
          					// prevent form submit to be able to see console output
          					event.preventDefault();
          					
          				function handle() {
          					if ( validator.settings.submitHandler ) {
          						if (validator.submitButton) {
          							// insert a hidden input as a replacement for the missing submit button
          							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
          						}
          						validator.settings.submitHandler.call( validator, validator.currentForm );
          						if (validator.submitButton) {
          							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
          							hidden.remove();
          						}
          						return false;
          					}
          					return true;
          				}
          					
          				// prevent submit for invalid forms or custom submit handlers
          				if ( validator.cancelSubmit ) {
          					validator.cancelSubmit = false;
          					return handle();
          				}
          				if ( validator.form() ) {
          					if ( validator.pendingRequest ) {
          						validator.formSubmitted = true;
          						return false;
          					}
          					return handle();
          				} else {
          					validator.focusInvalid();
          					return false;
          				}
          			});
          		}
          		
          		return validator;
          	},
          	// http://docs.jquery.com/Plugins/Validation/valid
          	valid: function() {
                  if ( $(this[0]).is('form')) {
                      return this.validate().form();
                  } else {
                      var valid = true;
                      var validator = $(this[0].form).validate();
                      this.each(function() {
          				valid &= validator.element(this);
                      });
                      return valid;
                  }
              },
          	// attributes: space seperated list of attributes to retrieve and remove
          	removeAttrs: function(attributes) {
          		var result = {},
          			$element = this;
          		$.each(attributes.split(/\s/), function(index, value) {
          			result[value] = $element.attr(value);
          			$element.removeAttr(value);
          		});
          		return result;
          	},
          	// http://docs.jquery.com/Plugins/Validation/rules
          	rules: function(command, argument) {
          		var element = this[0];
          		
          		if (command) {
          			var settings = $.data(element.form, 'validator').settings;
          			var staticRules = settings.rules;
          			var existingRules = $.validator.staticRules(element);
          			switch(command) {
          			case "add":
          				$.extend(existingRules, $.validator.normalizeRule(argument));
          				staticRules[element.name] = existingRules;
          				if (argument.messages)
          					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
          				break;
          			case "remove":
          				if (!argument) {
          					delete staticRules[element.name];
          					return existingRules;
          				}
          				var filtered = {};
          				$.each(argument.split(/\s/), function(index, method) {
          					filtered[method] = existingRules[method];
          					delete existingRules[method];
          				});
          				return filtered;
          			}
          		}
          		
          		var data = $.validator.normalizeRules(
          		$.extend(
          			{},
          			$.validator.metadataRules(element),
          			$.validator.classRules(element),
          			$.validator.attributeRules(element),
          			$.validator.staticRules(element)
          		), element);
          		
          		// make sure required is at front
          		if (data.required) {
          			var param = data.required;
          			delete data.required;
          			data = $.extend({required: param}, data);
          		}
          		
          		return data;
          	}
          });
          
          // Custom selectors
          $.extend($.expr[":"], {
          	// http://docs.jquery.com/Plugins/Validation/blank
          	blank: function(a) {return !$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/filled
          	filled: function(a) {return !!$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/unchecked
          	unchecked: function(a) {return !a.checked;}
          });
          
          // constructor for validator
          $.validator = function( options, form ) {
          	this.settings = $.extend( true, {}, $.validator.defaults, options );
          	this.currentForm = form;
          	this.init();
          };
          
          $.validator.format = function(source, params) {
          	if ( arguments.length == 1 ) 
          		return function() {
          			var args = $.makeArray(arguments);
          			args.unshift(source);
          			return $.validator.format.apply( this, args );
          		};
          	if ( arguments.length > 2 && params.constructor != Array  ) {
          		params = $.makeArray(arguments).slice(1);
          	}
          	if ( params.constructor != Array ) {
          		params = [ params ];
          	}
          	$.each(params, function(i, n) {
          		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
          	});
          	return source;
          };
          
          $.extend($.validator, {
          	
          	defaults: {
          		messages: {},
          		groups: {},
          		rules: {},
          		errorClass: "error",
          		validClass: "valid",
          		errorElement: "label",
          		focusInvalid: true,
          		errorContainer: $( [] ),
          		errorLabelContainer: $( [] ),
          		onsubmit: true,
          		ignore: [],
          		ignoreTitle: false,
          		onfocusin: function(element) {
          			this.lastActive = element;
          				
          			// hide error label and remove error class on focus if enabled
          			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
          				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
          				this.errorsFor(element).hide();
          			}
          		},
          		onfocusout: function(element) {
          			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
          				this.element(element);
          			}
          		},
          		onkeyup: function(element) {
          			if ( element.name in this.submitted || element == this.lastElement ) {
          				this.element(element);
          			}
          		},
          		onclick: function(element) {
          			// click on selects, radiobuttons and checkboxes
          			if ( element.name in this.submitted )
          				this.element(element);
          			// or option elements, check parent select in that case
          			else if (element.parentNode.name in this.submitted)
          				this.element(element.parentNode);
          		},
          		highlight: function( element, errorClass, validClass ) {
          			$(element).addClass(errorClass).removeClass(validClass);
          		},
          		unhighlight: function( element, errorClass, validClass ) {
          			$(element).removeClass(errorClass).addClass(validClass);
          		}
          	},
          
          	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
          	setDefaults: function(settings) {
          		$.extend( $.validator.defaults, settings );
          	},
          
          	messages: {
          		required: "This field is required.",
          		remote: "Please fix this field.",
          		email: "Please enter a valid email address.",
          		url: "Please enter a valid URL.",
          		date: "Please enter a valid date.",
          		dateISO: "Please enter a valid date (ISO).",
          		number: "Please enter a valid number.",
          		digits: "Please enter only digits.",
          		creditcard: "Please enter a valid credit card number.",
          		equalTo: "Please enter the same value again.",
          		accept: "Please enter a value with a valid extension.",
          		maxlength: $.validator.format("Please enter no more than {0} characters."),
          		minlength: $.validator.format("Please enter at least {0} characters."),
          		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
          		range: $.validator.format("Please enter a value between {0} and {1}."),
          		max: $.validator.format("Please enter a value less than or equal to {0}."),
          		min: $.validator.format("Please enter a value greater than or equal to {0}.")
          	},
          	
          	autoCreateRanges: false,
          	
          	prototype: {
          		
          		init: function() {
          			this.labelContainer = $(this.settings.errorLabelContainer);
          			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
          			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
          			this.submitted = {};
          			this.valueCache = {};
          			this.pendingRequest = 0;
          			this.pending = {};
          			this.invalid = {};
          			this.reset();
          			
          			var groups = (this.groups = {});
          			$.each(this.settings.groups, function(key, value) {
          				$.each(value.split(/\s/), function(index, name) {
          					groups[name] = key;
          				});
          			});
          			var rules = this.settings.rules;
          			$.each(rules, function(key, value) {
          				rules[key] = $.validator.normalizeRule(value);
          			});
          			
          			function delegate(event) {
          				var validator = $.data(this[0].form, "validator"),
          					eventType = "on" + event.type.replace(/^validate/, "");
          				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
          			}
          			$(this.currentForm)
          				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
          				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);
          
          			if (this.settings.invalidHandler)
          				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/form
          		form: function() {
          			this.checkForm();
          			$.extend(this.submitted, this.errorMap);
          			this.invalid = $.extend({}, this.errorMap);
          			if (!this.valid())
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          			this.showErrors();
          			return this.valid();
          		},
          		
          		checkForm: function() {
          			this.prepareForm();
          			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
          				this.check( elements[i] );
          			}
          			return this.valid(); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/element
          		element: function( element ) {
          			element = this.clean( element );
          			this.lastElement = element;
          			this.prepareElement( element );
          			this.currentElements = $(element);
          			var result = this.check( element );
          			if ( result ) {
          				delete this.invalid[element.name];
          			} else {
          				this.invalid[element.name] = true;
          			}
          			if ( !this.numberOfInvalids() ) {
          				// Hide error containers on last error
          				this.toHide = this.toHide.add( this.containers );
          			}
          			this.showErrors();
          			return result;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
          		showErrors: function(errors) {
          			if(errors) {
          				// add items to error list and map
          				$.extend( this.errorMap, errors );
          				this.errorList = [];
          				for ( var name in errors ) {
          					this.errorList.push({
          						message: errors[name],
          						element: this.findByName(name)[0]
          					});
          				}
          				// remove items from success list
          				this.successList = $.grep( this.successList, function(element) {
          					return !(element.name in errors);
          				});
          			}
          			this.settings.showErrors
          				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
          				: this.defaultShowErrors();
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
          		resetForm: function() {
          			if ( $.fn.resetForm )
          				$( this.currentForm ).resetForm();
          			this.submitted = {};
          			this.prepareForm();
          			this.hideErrors();
          			this.elements().removeClass( this.settings.errorClass );
          		},
          		
          		numberOfInvalids: function() {
          			return this.objectLength(this.invalid);
          		},
          		
          		objectLength: function( obj ) {
          			var count = 0;
          			for ( var i in obj )
          				count++;
          			return count;
          		},
          		
          		hideErrors: function() {
          			this.addWrapper( this.toHide ).hide();
          		},
          		
          		valid: function() {
          			return this.size() == 0;
          		},
          		
          		size: function() {
          			return this.errorList.length;
          		},
          		
          		focusInvalid: function() {
          			if( this.settings.focusInvalid ) {
          				try {
          					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
          					.filter(":visible")
          					.focus()
          					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
          					.trigger("focusin");
          				} catch(e) {
          					// ignore IE throwing errors when focusing hidden elements
          				}
          			}
          		},
          		
          		findLastActive: function() {
          			var lastActive = this.lastActive;
          			return lastActive && $.grep(this.errorList, function(n) {
          				return n.element.name == lastActive.name;
          			}).length == 1 && lastActive;
          		},
          		
          		elements: function() {
          			var validator = this,
          				rulesCache = {};
          			
          			// select all valid inputs inside the form (no submit or reset buttons)
          			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
          			return $([]).add(this.currentForm.elements)
          			.filter(":input")
          			.not(":submit, :reset, :image, [disabled]")
          			.not( this.settings.ignore )
          			.filter(function() {
          				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
          			
          				// select only the first element for each name, and only those with rules specified
          				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
          					return false;
          				
          				rulesCache[this.name] = true;
          				return true;
          			});
          		},
          		
          		clean: function( selector ) {
          			return $( selector )[0];
          		},
          		
          		errors: function() {
          			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
          		},
          		
          		reset: function() {
          			this.successList = [];
          			this.errorList = [];
          			this.errorMap = {};
          			this.toShow = $([]);
          			this.toHide = $([]);
          			this.currentElements = $([]);
          		},
          		
          		prepareForm: function() {
          			this.reset();
          			this.toHide = this.errors().add( this.containers );
          		},
          		
          		prepareElement: function( element ) {
          			this.reset();
          			this.toHide = this.errorsFor(element);
          		},
          	
          		check: function( element ) {
          			element = this.clean( element );
          			
          			// if radio/checkbox, validate first element in group instead
          			if (this.checkable(element)) {
          				element = this.findByName( element.name )[0];
          			}
          			
          			var rules = $(element).rules();
          			var dependencyMismatch = false;
          			for( method in rules ) {
          				var rule = { method: method, parameters: rules[method] };
          				try {
          					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
          					
          					// if a method indicates that the field is optional and therefore valid,
          					// don't mark it as valid when there are no other rules
          					if ( result == "dependency-mismatch" ) {
          						dependencyMismatch = true;
          						continue;
          					}
          					dependencyMismatch = false;
          					
          					if ( result == "pending" ) {
          						this.toHide = this.toHide.not( this.errorsFor(element) );
          						return;
          					}
          					
          					if( !result ) {
          						this.formatAndAdd( element, rule );
          						return false;
          					}
          				} catch(e) {
          					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
          						 + ", check the '" + rule.method + "' method", e);
          					throw e;
          				}
          			}
          			if (dependencyMismatch)
          				return;
          			if ( this.objectLength(rules) )
          				this.successList.push(element);
          			return true;
          		},
          		
          		// return the custom message for the given element and validation method
          		// specified in the element's "messages" metadata
          		customMetaMessage: function(element, method) {
          			if (!$.metadata)
          				return;
          			
          			var meta = this.settings.meta
          				? $(element).metadata()[this.settings.meta]
          				: $(element).metadata();
          			
          			return meta && meta.messages && meta.messages[method];
          		},
          		
          		// return the custom message for the given element name and validation method
          		customMessage: function( name, method ) {
          			var m = this.settings.messages[name];
          			return m && (m.constructor == String
          				? m
          				: m[method]);
          		},
          		
          		// return the first defined argument, allowing empty strings
          		findDefined: function() {
          			for(var i = 0; i < arguments.length; i++) {
          				if (arguments[i] !== undefined)
          					return arguments[i];
          			}
          			return undefined;
          		},
          		
          		defaultMessage: function( element, method) {
          			return this.findDefined(
          				this.customMessage( element.name, method ),
          				this.customMetaMessage( element, method ),
          				// title is never undefined, so handle empty string as undefined
          				!this.settings.ignoreTitle && element.title || undefined,
          				$.validator.messages[method],
          				"<strong>Warning: No message defined for " + element.name + "</strong>"
          			);
          		},
          		
          		formatAndAdd: function( element, rule ) {
          			var message = this.defaultMessage( element, rule.method ),
          				theregex = /\$?\{(\d+)\}/g;
          			if ( typeof message == "function" ) {
          				message = message.call(this, rule.parameters, element);
          			} else if (theregex.test(message)) {
          				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
          			}			
          			this.errorList.push({
          				message: message,
          				element: element
          			});
          			
          			this.errorMap[element.name] = message;
          			this.submitted[element.name] = message;
          		},
          		
          		addWrapper: function(toToggle) {
          			if ( this.settings.wrapper )
          				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
          			return toToggle;
          		},
          		
          		defaultShowErrors: function() {
          			for ( var i = 0; this.errorList[i]; i++ ) {
          				var error = this.errorList[i];
          				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
          				this.showLabel( error.element, error.message );
          			}
          			if( this.errorList.length ) {
          				this.toShow = this.toShow.add( this.containers );
          			}
          			if (this.settings.success) {
          				for ( var i = 0; this.successList[i]; i++ ) {
          					this.showLabel( this.successList[i] );
          				}
          			}
          			if (this.settings.unhighlight) {
          				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
          					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
          				}
          			}
          			this.toHide = this.toHide.not( this.toShow );
          			this.hideErrors();
          			this.addWrapper( this.toShow ).show();
          		},
          		
          		validElements: function() {
          			return this.currentElements.not(this.invalidElements());
          		},
          		
          		invalidElements: function() {
          			return $(this.errorList).map(function() {
          				return this.element;
          			});
          		},
          		
          		showLabel: function(element, message) {
          			var label = this.errorsFor( element );
          			if ( label.length ) {
          				// refresh error/success class
          				label.removeClass().addClass( this.settings.errorClass );
          			
          				// check if we have a generated label, replace the message then
          				label.attr("generated") && label.html(message);
          			} else {
          				// create label
          				label = $("<" + this.settings.errorElement + "/>")
          					.attr({"for":  this.idOrName(element), generated: true})
          					.addClass(this.settings.errorClass)
          					.html(message || "");
          				if ( this.settings.wrapper ) {
          					// make sure the element is visible, even in IE
          					// actually showing the wrapped element is handled elsewhere
          					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
          				}
          				if ( !this.labelContainer.append(label).length )
          					this.settings.errorPlacement
          						? this.settings.errorPlacement(label, $(element) )
          						: label.insertAfter(element);
          			}
          			if ( !message && this.settings.success ) {
          				label.text("");
          				typeof this.settings.success == "string"
          					? label.addClass( this.settings.success )
          					: this.settings.success( label );
          			}
          			this.toShow = this.toShow.add(label);
          		},
          		
          		errorsFor: function(element) {
          			var name = this.idOrName(element);
              		return this.errors().filter(function() {
          				return $(this).attr('for') == name;
          			});
          		},
          		
          		idOrName: function(element) {
          			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
          		},
          
          		checkable: function( element ) {
          			return /radio|checkbox/i.test(element.type);
          		},
          		
          		findByName: function( name ) {
          			// select by name and filter by form for performance over form.find("[name=...]")
          			var form = this.currentForm;
          			return $(document.getElementsByName(name)).map(function(index, element) {
          				return element.form == form && element.name == name && element  || null;
          			});
          		},
          		
          		getLength: function(value, element) {
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				return $("option:selected", element).length;
          			case 'input':
          				if( this.checkable( element) )
          					return this.findByName(element.name).filter(':checked').length;
          			}
          			return value.length;
          		},
          	
          		depend: function(param, element) {
          			return this.dependTypes[typeof param]
          				? this.dependTypes[typeof param](param, element)
          				: true;
          		},
          	
          		dependTypes: {
          			"boolean": function(param, element) {
          				return param;
          			},
          			"string": function(param, element) {
          				return !!$(param, element.form).length;
          			},
          			"function": function(param, element) {
          				return param(element);
          			}
          		},
          		
          		optional: function(element) {
          			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
          		},
          		
          		startRequest: function(element) {
          			if (!this.pending[element.name]) {
          				this.pendingRequest++;
          				this.pending[element.name] = true;
          			}
          		},
          		
          		stopRequest: function(element, valid) {
          			this.pendingRequest--;
          			// sometimes synchronization fails, make sure pendingRequest is never < 0
          			if (this.pendingRequest < 0)
          				this.pendingRequest = 0;
          			delete this.pending[element.name];
          			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
          				$(this.currentForm).submit();
          				this.formSubmitted = false;
          			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          				this.formSubmitted = false;
          			}
          		},
          		
          		previousValue: function(element) {
          			return $.data(element, "previousValue") || $.data(element, "previousValue", {
          				old: null,
          				valid: true,
          				message: this.defaultMessage( element, "remote" )
          			});
          		}
          		
          	},
          	
          	classRuleSettings: {
          		required: {required: true},
          		email: {email: true},
          		url: {url: true},
          		date: {date: true},
          		dateISO: {dateISO: true},
          		dateDE: {dateDE: true},
          		number: {number: true},
          		numberDE: {numberDE: true},
          		digits: {digits: true},
          		creditcard: {creditcard: true}
          	},
          	
          	addClassRules: function(className, rules) {
          		className.constructor == String ?
          			this.classRuleSettings[className] = rules :
          			$.extend(this.classRuleSettings, className);
          	},
          	
          	classRules: function(element) {
          		var rules = {};
          		var classes = $(element).attr('class');
          		classes && $.each(classes.split(' '), function() {
          			if (this in $.validator.classRuleSettings) {
          				$.extend(rules, $.validator.classRuleSettings[this]);
          			}
          		});
          		return rules;
          	},
          	
          	attributeRules: function(element) {
          		var rules = {};
          		var $element = $(element);
          		
          		for (method in $.validator.methods) {
          			var value = $element.attr(method);
          			if (value) {
          				rules[method] = value;
          			}
          		}
          		
          		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
          		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
          			delete rules.maxlength;
          		}
          		
          		return rules;
          	},
          	
          	metadataRules: function(element) {
          		if (!$.metadata) return {};
          		
          		var meta = $.data(element.form, 'validator').settings.meta;
          		return meta ?
          			$(element).metadata()[meta] :
          			$(element).metadata();
          	},
          	
          	staticRules: function(element) {
          		var rules = {};
          		var validator = $.data(element.form, 'validator');
          		if (validator.settings.rules) {
          			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
          		}
          		return rules;
          	},
          	
          	normalizeRules: function(rules, element) {
          		// handle dependency check
          		$.each(rules, function(prop, val) {
          			// ignore rule when param is explicitly false, eg. required:false
          			if (val === false) {
          				delete rules[prop];
          				return;
          			}
          			if (val.param || val.depends) {
          				var keepRule = true;
          				switch (typeof val.depends) {
          					case "string":
          						keepRule = !!$(val.depends, element.form).length;
          						break;
          					case "function":
          						keepRule = val.depends.call(element, element);
          						break;
          				}
          				if (keepRule) {
          					rules[prop] = val.param !== undefined ? val.param : true;
          				} else {
          					delete rules[prop];
          				}
          			}
          		});
          		
          		// evaluate parameters
          		$.each(rules, function(rule, parameter) {
          			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
          		});
          		
          		// clean number parameters
          		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
          			if (rules[this]) {
          				rules[this] = Number(rules[this]);
          			}
          		});
          		$.each(['rangelength', 'range'], function() {
          			if (rules[this]) {
          				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
          			}
          		});
          		
          		if ($.validator.autoCreateRanges) {
          			// auto-create ranges
          			if (rules.min && rules.max) {
          				rules.range = [rules.min, rules.max];
          				delete rules.min;
          				delete rules.max;
          			}
          			if (rules.minlength && rules.maxlength) {
          				rules.rangelength = [rules.minlength, rules.maxlength];
          				delete rules.minlength;
          				delete rules.maxlength;
          			}
          		}
          		
          		// To support custom messages in metadata ignore rule methods titled "messages"
          		if (rules.messages) {
          			delete rules.messages;
          		}
          		
          		return rules;
          	},
          	
          	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
          	normalizeRule: function(data) {
          		if( typeof data == "string" ) {
          			var transformed = {};
          			$.each(data.split(/\s/), function() {
          				transformed[this] = true;
          			});
          			data = transformed;
          		}
          		return data;
          	},
          	
          	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
          	addMethod: function(name, method, message) {
          		$.validator.methods[name] = method;
          		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
          		if (method.length < 3) {
          			$.validator.addClassRules(name, $.validator.normalizeRule(name));
          		}
          	},
          
          	methods: {
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/required
          		required: function(value, element, param) {
          			// check if dependency is met
          			if ( !this.depend(param, element) )
          				return "dependency-mismatch";
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				// could be an array for select-multiple or a string, both are fine this way
          				var val = $(element).val();
          				return val && val.length > 0;
          			case 'input':
          				if ( this.checkable(element) )
          					return this.getLength(value, element) > 0;
          			default:
          				return $.trim(value).length > 0;
          			}
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/remote
          		remote: function(value, element, param) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			
          			var previous = this.previousValue(element);
          			if (!this.settings.messages[element.name] )
          				this.settings.messages[element.name] = {};
          			previous.originalMessage = this.settings.messages[element.name].remote;
          			this.settings.messages[element.name].remote = previous.message;
          			
          			param = typeof param == "string" && {url:param} || param; 
          			
          			if ( previous.old !== value ) {
          				previous.old = value;
          				var validator = this;
          				this.startRequest(element);
          				var data = {};
          				data[element.name] = value;
          				$.ajax($.extend(true, {
          					url: param,
          					mode: "abort",
          					port: "validate" + element.name,
          					dataType: "json",
          					data: data,
          					success: function(response) {
          						validator.settings.messages[element.name].remote = previous.originalMessage;
          						var valid = response === true;
          						if ( valid ) {
          							var submitted = validator.formSubmitted;
          							validator.prepareElement(element);
          							validator.formSubmitted = submitted;
          							validator.successList.push(element);
          							validator.showErrors();
          						} else {
          							var errors = {};
          							var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
          							errors[element.name] = $.isFunction(message) ? message(value) : message;
          							validator.showErrors(errors);
          						}
          						previous.valid = valid;
          						validator.stopRequest(element, valid);
          					}
          				}, param));
          				return "pending";
          			} else if( this.pending[element.name] ) {
          				return "pending";
          			}
          			return previous.valid;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
          		minlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
          		maxlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
          		rangelength: function(value, element, param) {
          			var length = this.getLength($.trim(value), element);
          			return this.optional(element) || ( length >= param[0] && length <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/min
          		min: function( value, element, param ) {
          			return this.optional(element) || value >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/max
          		max: function( value, element, param ) {
          			return this.optional(element) || value <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/range
          		range: function( value, element, param ) {
          			return this.optional(element) || ( value >= param[0] && value <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/email
          		email: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
          			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/url
          		url: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
          			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
          		},
                  
          		// http://docs.jquery.com/Plugins/Validation/Methods/date
          		date: function(value, element) {
          			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
          		dateISO: function(value, element) {
          			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/number
          		number: function(value, element) {
          			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/digits
          		digits: function(value, element) {
          			return this.optional(element) || /^\d+$/.test(value);
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
          		// based on http://en.wikipedia.org/wiki/Luhn
          		creditcard: function(value, element) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			// accept only digits and dashes
          			if (/[^0-9-]+/.test(value))
          				return false;
          			var nCheck = 0,
          				nDigit = 0,
          				bEven = false;
          
          			value = value.replace(/\D/g, "");
          
          			for (var n = value.length - 1; n >= 0; n--) {
          				var cDigit = value.charAt(n);
          				var nDigit = parseInt(cDigit, 10);
          				if (bEven) {
          					if ((nDigit *= 2) > 9)
          						nDigit -= 9;
          				}
          				nCheck += nDigit;
          				bEven = !bEven;
          			}
          
          			return (nCheck % 10) == 0;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/accept
          		accept: function(value, element, param) {
          			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
          			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
          		equalTo: function(value, element, param) {
          			// bind to the blur event of the target in order to revalidate whenever the target field is updated
          			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
          			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
          				$(element).valid();
          			});
          			return value == target.val();
          		}
          		
          	}
          	
          });
          
          // deprecated, use $.validator.format instead
          $.format = $.validator.format;
          
          })(jQuery);
          
          // ajax mode: abort
          // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
          // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
          ;(function($) {
          	var ajax = $.ajax;
          	var pendingRequests = {};
          	$.ajax = function(settings) {
          		// create settings for compatibility with ajaxSetup
          		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
          		var port = settings.port;
          		if (settings.mode == "abort") {
          			if ( pendingRequests[port] ) {
          				pendingRequests[port].abort();
          			}
          			return (pendingRequests[port] = ajax.apply(this, arguments));
          		}
          		return ajax.apply(this, arguments);
          	};
          })(jQuery);
          
          // provides cross-browser focusin and focusout events
          // IE has native support, in other browsers, use event caputuring (neither bubbles)
          
          // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
          // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
          ;(function($) {
          	// only implement if not provided by jQuery core (since 1.4)
          	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
          	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
          		$.each({
          			focus: 'focusin',
          			blur: 'focusout'	
          		}, function( original, fix ){
          			$.event.special[fix] = {
          				setup:function() {
          					this.addEventListener( original, handler, true );
          				},
          				teardown:function() {
          					this.removeEventListener( original, handler, true );
          				},
          				handler: function(e) {
          					arguments[0] = $.event.fix(e);
          					arguments[0].type = fix;
          					return $.event.handle.apply(this, arguments);
          				}
          			};
          			function handler(e) {
          				e = $.event.fix(e);
          				e.type = fix;
          				return $.event.handle.call(this, e);
          			}
          		});
          	};
          	$.extend($.fn, {
          		validateDelegate: function(delegate, type, handler) {
          			return this.bind(type, function(event) {
          				var target = $(event.target);
          				if (target.is(delegate)) {
          					return handler.apply(target, arguments);
          				}
          			});
          		}
          	});
          })(jQuery);
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        14. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (393 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 10254
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10254-1268025194000"
          Last-Modified: Mon, 08 Mar 2010 05:13:14 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10254 bytes)
          /*!
           * jQuery throttle / debounce - v1.1 - 3/7/2010
           * http://benalman.com/projects/jquery-throttle-debounce-plugin/
           * 
           * Copyright (c) 2010 "Cowboy" Ben Alman
           * Dual licensed under the MIT and GPL licenses.
           * http://benalman.com/about/license/
           */
          
          // Script: jQuery throttle / debounce: Sometimes, less is more!
          //
          // *Version: 1.1, Last updated: 3/7/2010*
          // 
          // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
          // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
          // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
          // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
          // 
          // About: License
          // 
          // Copyright (c) 2010 "Cowboy" Ben Alman,
          // Dual licensed under the MIT and GPL licenses.
          // http://benalman.com/about/license/
          // 
          // About: Examples
          // 
          // These working examples, complete with fully commented code, illustrate a few
          // ways in which this plugin can be used.
          // 
          // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
          // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
          // 
          // About: Support and Testing
          // 
          // Information about what version or versions of jQuery this plugin has been
          // tested with, what browsers it has been tested in, and where the unit tests
          // reside (so you can test it yourself).
          // 
          // jQuery Versions - none, 1.3.2, 1.4.2
          // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
          // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
          // 
          // About: Release History
          // 
          // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
          //       executed later than they should. Reworked a fair amount of internal
          //       logic as well.
          // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
          //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
          //       no_trailing throttle parameter and debounce functionality.
          // 
          // Topic: Note for non-jQuery users
          // 
          // jQuery isn't actually required for this plugin, because nothing internal
          // uses any jQuery methods or properties. jQuery is just used as a namespace
          // under which these methods can exist.
          // 
          // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
          // when this plugin is loaded, the method described below will be created in
          // the `Cowboy` namespace. Usage will be exactly the same, but instead of
          // $.method() or jQuery.method(), you'll need to use Cowboy.method().
          
          (function(window,undefined){
            '$:nomunge'; // Used by YUI compressor.
            
            // Since jQuery really isn't required for this plugin, use `jQuery` as the
            // namespace only if it already exists, otherwise use the `Cowboy` namespace,
            // creating it if necessary.
            var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
              
              // Internal method reference.
              jq_throttle;
            
            // Method: jQuery.throttle
            // 
            // Throttle execution of a function. Especially useful for rate limiting
            // execution of handlers on events like resize and scroll. If you want to
            // rate-limit execution of a function to a single time, see the
            // <jQuery.debounce> method.
            // 
            // In this visualization, | is a throttled-function call and X is the actual
            // callback execution:
            // 
            // > Throttled with `no_trailing` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X    X        X    X    X    X    X    X
            // > 
            // > Throttled with `no_trailing` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X             X    X    X    X    X
            // 
            // Usage:
            // 
            // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', throttled );
            // > jQuery('selector').unbind( 'someevent', throttled );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
            //    true, callback will only execute every `delay` milliseconds while the
            //    throttled-function is being called. If no_trailing is false or
            //    unspecified, callback will be executed one final time after the last
            //    throttled-function call. (After the throttled-function has not been
            //    called for `delay` milliseconds, the internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the throttled-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, throttled, function.
            
            $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
              // After wrapper has stopped being called, this timeout ensures that
              // `callback` is executed at the proper times in `throttle` and `end`
              // debounce modes.
              var timeout_id,
                
                // Keep track of the last time `callback` was executed.
                last_exec = 0;
              
              // `no_trailing` defaults to falsy.
              if ( typeof no_trailing !== 'boolean' ) {
                debounce_mode = callback;
                callback = no_trailing;
                no_trailing = undefined;
              }
              
              // The `wrapper` function encapsulates all of the throttling / debouncing
              // functionality and when executed will limit the rate at which `callback`
              // is executed.
              function wrapper() {
                var that = this,
                  elapsed = +new Date() - last_exec,
                  args = arguments;
                
                // Execute `callback` and update the `last_exec` timestamp.
                function exec() {
                  last_exec = +new Date();
                  callback.apply( that, args );
                };
                
                // If `debounce_mode` is true (at_begin) this is used to clear the flag
                // to allow future `callback` executions.
                function clear() {
                  timeout_id = undefined;
                };
                
                if ( debounce_mode && !timeout_id ) {
                  // Since `wrapper` is being called for the first time and
                  // `debounce_mode` is true (at_begin), execute `callback`.
                  exec();
                }
                
                // Clear any existing timeout.
                timeout_id && clearTimeout( timeout_id );
                
                if ( debounce_mode === undefined && elapsed > delay ) {
                  // In throttle mode, if `delay` time has been exceeded, execute
                  // `callback`.
                  exec();
                  
                } else if ( no_trailing !== true ) {
                  // In trailing throttle mode, since `delay` time has not been
                  // exceeded, schedule `callback` to execute `delay` ms after most
                  // recent execution.
                  // 
                  // If `debounce_mode` is true (at_begin), schedule `clear` to execute
                  // after `delay` ms.
                  // 
                  // If `debounce_mode` is false (at end), schedule `callback` to
                  // execute after `delay` ms.
                  timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
                }
              };
              
              // Set the guid of `wrapper` function to the same of original callback, so
              // it can be removed in jQuery 1.4+ .unbind or .die by using the original
              // callback as a reference.
              if ( $.guid ) {
                wrapper.guid = callback.guid = callback.guid || $.guid++;
              }
              
              // Return the wrapper function.
              return wrapper;
            };
            
            // Method: jQuery.debounce
            // 
            // Debounce execution of a function. Debouncing, unlike throttling,
            // guarantees that a function is only executed a single time, either at the
            // very beginning of a series of calls, or at the very end. If you want to
            // simply rate-limit execution of a function, see the <jQuery.throttle>
            // method.
            // 
            // In this visualization, | is a debounced-function call and X is the actual
            // callback execution:
            // 
            // > Debounced with `at_begin` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // >                          X                                 X
            // > 
            // > Debounced with `at_begin` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X                                 X
            // 
            // Usage:
            // 
            // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', debounced );
            // > jQuery('selector').unbind( 'someevent', debounced );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
            //    unspecified, callback will only be executed `delay` milliseconds after
            //    the last debounced-function call. If at_begin is true, callback will be
            //    executed only at the first debounced-function call. (After the
            //    throttled-function has not been called for `delay` milliseconds, the
            //    internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the debounced-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, debounced, function.
            
            $.debounce = function( delay, at_begin, callback ) {
              return callback === undefined
                ? jq_throttle( delay, at_begin, false )
                : jq_throttle( delay, callback, at_begin !== false );
            };
            
          })(this);
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        15. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (398 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 2441
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"2441-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (2441 bytes)
          .dropdown {
          	position: absolute;
          	z-index: 9999999;
          	display: none;
          }
          
          .dropdown .dropdown-menu,
          .dropdown .dropdown-panel {
          	min-width: 160px;
          	max-width: 360px;
          	list-style: none;
          	background: #FFF;
          	border: solid 1px #DDD;
          	border: solid 1px rgba(0, 0, 0, .2);
          	border-radius: 6px;
          	box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
          	overflow: visible;
          	padding: 4px 0;
          	margin: 0;
          }
          
          .dropdown .dropdown-panel {
          	padding: 10px;
          }
          
          .dropdown.dropdown-tip {
          	margin-top: 8px;
          }
          
          .dropdown.dropdown-tip:before {
            position: absolute;
            top: -6px;
            left: 9px;
            content: '';
            border-left: 7px solid transparent;
            border-right: 7px solid transparent;
            border-bottom: 7px solid #CCC;
            border-bottom-color: rgba(0, 0, 0, 0.2);
            display: inline-block;
          }
          
          .dropdown.dropdown-tip.dropdown-anchor-right:before {
          	left: auto;
          	right: 9px;
          }
          
          .dropdown.dropdown-tip:after {
            position: absolute;
            top: -5px;
            left: 10px;
            content: '';
            border-left: 6px solid transparent;
            border-right: 6px solid transparent;
            border-bottom: 6px solid #FFF;
            display: inline-block;
          }
          
          .dropdown.dropdown-tip.dropdown-anchor-right:after {
          	left: auto;
          	right: 10px;
          }
          
          
          .dropdown.dropdown-scroll .dropdown-menu,
          .dropdown.dropdown-scroll .dropdown-panel {
          	max-height: 358px;
          	overflow: auto;
          }
          
          .dropdown .dropdown-menu LI {
          	list-style: none;
          	padding: 0 0;
          	margin: 0;
          	line-height: 18px;
          }
          
          .dropdown .dropdown-menu LI > A,
          .dropdown .dropdown-menu LABEL {
          	display: block;
          	color: #555;
          	text-decoration: none;
          	line-height: 18px;
          	padding: 3px 15px;
          	margin: 0;
          	white-space: nowrap;
          }
          
          .dropdown .dropdown-menu LI > A:hover,
          .dropdown .dropdown-menu LABEL:hover {
          	background-color: #08C;
          	color: #FFF;
          	cursor: pointer;
          }
          
          .dropdown .dropdown-menu .dropdown-divider {
          	font-size: 1px;
          	border-top: solid 1px #E5E5E5;
          	padding: 0;
          	margin: 5px 0;
          }
          
          /* Icon Examples - icons courtesy of http://p.yusukekamiyamane.com/ */
          .dropdown.has-icons LI > A {
          	padding-left: 30px;
          	background-position: 8px center;
          	background-repeat: no-repeat;
          }
          
          .dropdown .undo A { background-image: url(icons/arrow-curve-180-left.png); }
          .dropdown .redo A { background-image: url(icons/arrow-curve.png); }
          .dropdown .cut A { background-image: url(icons/scissors.png); }
          .dropdown .copy A { background-image: url(icons/document-copy.png); }
          .dropdown .paste A { background-image: url(icons/clipboard.png); }
          .dropdown .delete A { background-image: url(icons/cross-script.png); }
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        16. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (401 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 2131
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"2131-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (2131 bytes)
          /*
           * jQuery dropdown: A simple dropdown plugin
           *
           * Copyright A Beautiful Site, LLC. (http://www.abeautifulsite.net/)
           *
           * Licensed under the MIT license: http://opensource.org/licenses/MIT
           *
          */jQuery&&function(e){function t(t,i){var s=t?e(this):i,o=e(s.attr("data-dropdown")),u=s.hasClass("dropdown-open");if(t){if(e(t.target).hasClass("dropdown-ignore"))return;t.preventDefault();t.stopPropagation()}else if(s!==i.target&&e(i.target).hasClass("dropdown-ignore"))return;n();if(u||s.hasClass("dropdown-disabled"))return;s.addClass("dropdown-open");o.data("dropdown-trigger",s).show();r();o.trigger("show",{dropdown:o,trigger:s})}function n(t){var n=t?e(t.target).parents().addBack():null;if(n&&n.is(".dropdown")){if(!n.is(".dropdown-menu"))return;if(!n.is("A"))return}e(document).find(".dropdown:visible").each(function(){var t=e(this);t.hide().removeData("dropdown-trigger").trigger("hide",{dropdown:t})});e(document).find(".dropdown-open").removeClass("dropdown-open")}function r(){var t=e(".dropdown:visible").eq(0),n=t.data("dropdown-trigger"),r=n?parseInt(n.attr("data-horizontal-offset")||0,10):null,i=n?parseInt(n.attr("data-vertical-offset")||0,10):null;if(t.length===0||!n)return;t.hasClass("dropdown-relative")?t.css({left:t.hasClass("dropdown-anchor-right")?n.position().left-(t.outerWidth(!0)-n.outerWidth(!0))-parseInt(n.css("margin-right"),10)+r:n.position().left+parseInt(n.css("margin-left"),10)+r,top:n.position().top+n.outerHeight(!0)-parseInt(n.css("margin-top"),10)+i}):t.css({left:t.hasClass("dropdown-anchor-right")?n.offset().left-(t.outerWidth()-n.outerWidth())+r:n.offset().left+r,top:n.offset().top+n.outerHeight()+i})}e.extend(e.fn,{dropdown:function(r,i){switch(r){case"show":t(null,e(this));return e(this);case"hide":n();return e(this);case"attach":return e(this).attr("data-dropdown",i);case"detach":n();return e(this).removeAttr("data-dropdown");case"disable":return e(this).addClass("dropdown-disabled");case"enable":n();return e(this).removeClass("dropdown-disabled")}}});e(document).on("click.dropdown","[data-dropdown]",t);e(document).on("click.dropdown",n);e(window).on("resize",r)}(jQuery);
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        17. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (419 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 6717
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"6717-1265153602000"
          Last-Modified: Tue, 02 Feb 2010 23:33:22 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (6717 bytes)
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           * 
           * Open source under the BSD License. 
           * 
           * Copyright © 2008 George McGinley Smith
           * All rights reserved.
           * 
           * Redistribution and use in source and binary forms, with or without modification, 
           * are permitted provided that the following conditions are met:
           * 
           * Redistributions of source code must retain the above copyright notice, this list of 
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list 
           * of conditions and the following disclaimer in the documentation and/or other materials 
           * provided with the distribution.
           * 
           * Neither the name of the author nor the names of contributors may be used to endorse 
           * or promote products derived from this software without specific prior written permission.
           * 
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
           * OF THE POSSIBILITY OF SUCH DAMAGE. 
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{}))
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           * 
           * Open source under the BSD License. 
           * 
           * Copyright © 2001 Robert Penner
           * All rights reserved.
           * 
           * Redistribution and use in source and binary forms, with or without modification, 
           * are permitted provided that the following conditions are met:
           * 
           * Redistributions of source code must retain the above copyright notice, this list of 
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list 
           * of conditions and the following disclaimer in the documentation and/or other materials 
           * provided with the distribution.
           * 
           * Neither the name of the author nor the names of contributors may be used to endorse 
           * or promote products derived from this software without specific prior written permission.
           * 
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
           * OF THE POSSIBILITY OF SUCH DAMAGE. 
           *
           */
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        18. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (419 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 8285
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"8285-1267811252000"
          Last-Modified: Fri, 05 Mar 2010 17:47:32 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (8285 bytes)
          /*
           * FancyBox - jQuery Plugin
           * Simple and fancy lightbox alternative
           *
           * Examples and documentation at: http://fancybox.net
           * 
           * Copyright (c) 2008 - 2010 Janis Skarnelis
           *
           * Version: 1.3.1 (05/03/2010)
           * Requires: jQuery v1.3+
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          #fancybox-loading {
          	position: fixed;
          	top: 50%;
          	left: 50%;
          	height: 40px;
          	width: 40px;
          	margin-top: -20px;
          	margin-left: -20px;
          	cursor: pointer;
          	overflow: hidden;
          	z-index: 1104;
          	display: none;
          }
          
          * html #fancybox-loading {	/* IE6 */
          	position: absolute;
          	margin-top: 0;
          }
          
          #fancybox-loading div {
          	position: absolute;
          	top: 0;
          	left: 0;
          	width: 40px;
          	height: 480px;
          	background-image: url('fancybox.png');
          }
          
          #fancybox-overlay {
          	position: fixed;
          	top: 0;
          	left: 0;
          	bottom: 0;
          	right: 0;
          	background: #000;
          	z-index: 1100;
          	display: none;
          }
          
          * html #fancybox-overlay {	/* IE6 */
          	position: absolute;
          	width: 100%;
          }
          
          #fancybox-tmp {
          	padding: 0;
          	margin: 0;
          	border: 0;
          	overflow: auto;
          	display: none;
          }
          
          #fancybox-wrap {
          	position: absolute;
          	top: 0;
          	left: 0;
          	margin: 0;
          	padding: 20px;
          	z-index: 1101;
          	display: none;
          }
          
          #fancybox-outer {
          	position: relative;
          	width: 100%;
          	height: 100%;
          	background: #FFF;
          }
          
          #fancybox-inner {
          	position: absolute;
          	top: 0;
          	left: 0;
          	width: 1px;
          	height: 1px;
          	padding: 0;
          	margin: 0;
          	outline: none;
          	overflow: hidden;
          }
          
          #fancybox-hide-sel-frame {
          	position: absolute;
          	top: 0;
          	left: 0;
          	width: 100%;
          	height: 100%;
          	background: transparent;
          }
          
          #fancybox-close {
          	position: absolute;
          	top: -15px;
          	right: -15px;
          	width: 30px;
          	height: 30px;
          	background-image: url('fancybox.png');
          	background-position: -40px 0px;
          	cursor: pointer;
          	z-index: 1103;
          	display: none;
          }
          
          #fancybox_error {
          	color: #444;
          	font: normal 12px/20px Arial;
          	padding: 7px;
          	margin: 0;
          }
          
          #fancybox-content {
          	height: auto;
          	width: auto;
          	padding: 0;
          	margin: 0;
          }
          
          #fancybox-img {
          	width: 100%;
          	height: 100%;
          	padding: 0;
          	margin: 0;
          	border: none;
          	outline: none;
          	line-height: 0;
          	vertical-align: top;
          	-ms-interpolation-mode: bicubic;
          }
          
          #fancybox-frame {
          	position: relative;
          	width: 100%;
          	height: 100%;
          	border: none;
          	display: block;
          }
          
          #fancybox-title {
          	position: absolute;
          	bottom: 0;
          	left: 0;
          	font-family: Arial;
          	font-size: 12px;
          	z-index: 1102;
          }
          
          .fancybox-title-inside {
          	padding: 10px 0;
          	text-align: center;
          	color: #333;
          }
          
          .fancybox-title-outside {
          	padding-top: 5px;
          	color: #FFF;
          	text-align: center;
          	font-weight: bold;
          }
          
          .fancybox-title-over {
          	color: #FFF;
          	text-align: left;
          }
          
          #fancybox-title-over {
          	padding: 10px;
          	background-image: url('fancy_title_over.png');
          	display: block;
          }
          
          #fancybox-title-wrap {
          	display: inline-block;
          }
          
          #fancybox-title-wrap span {
          	height: 32px;
          	float: left;
          }
          
          #fancybox-title-left {
          	padding-left: 15px;
          	background-image: url('fancybox.png');
          	background-position: -40px -90px;
          	background-repeat: no-repeat;
          }
          
          #fancybox-title-main {
          	font-weight: bold;
          	line-height: 29px;
          	background-image: url('fancybox-x.png');
          	background-position: 0px -40px;
          	color: #FFF;
          }
          
          #fancybox-title-right {
          	padding-left: 15px;
          	background-image: url('fancybox.png');
          	background-position: -55px -90px;
          	background-repeat: no-repeat;
          }
          
          #fancybox-left, #fancybox-right {
          	position: absolute;
          	bottom: 0px;
          	height: 100%;
          	width: 35%;
          	cursor: pointer;
          	outline: none;
          	background-image: url('blank.gif');
          	z-index: 1102;
          	display: none;
          }
          
          #fancybox-left {
          	left: 0px;
          }
          
          #fancybox-right {
          	right: 0px;
          }
          
          #fancybox-left-ico, #fancybox-right-ico {
          	position: absolute;
          	top: 50%;
          	left: -9999px;
          	width: 30px;
          	height: 30px;
          	margin-top: -15px;
          	cursor: pointer;
          	z-index: 1102;
          	display: block;
          }
          
          #fancybox-left-ico {
          	background-image: url('fancybox.png');
          	background-position: -40px -30px;
          }
          
          #fancybox-right-ico {
          	background-image: url('fancybox.png');
          	background-position: -40px -60px;
          }
          
          #fancybox-left:hover, #fancybox-right:hover {
          	visibility: visible;    /* IE6 */
          }
          
          #fancybox-left:hover span {
          	left: 20px;
          }
          
          #fancybox-right:hover span {
          	left: auto;
          	right: 20px;
          }
          
          .fancy-bg {
          	position: absolute;
          	padding: 0;
          	margin: 0;
          	border: 0;
          	width: 20px;
          	height: 20px;
          	z-index: 1001;
          }
          
          #fancy-bg-n {
          	top: -20px;
          	left: 0;
          	width: 100%;
          	background-image: url('fancybox-x.png');
          }
          
          #fancy-bg-ne {
          	top: -20px;
          	right: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -162px;
          }
          
          #fancy-bg-e {
          	top: 0;
          	right: -20px;
          	height: 100%;
          	background-image: url('fancybox-y.png');
          	background-position: -20px 0px;
          }
          
          #fancy-bg-se {
          	bottom: -20px;
          	right: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -182px; 
          }
          
          #fancy-bg-s {
          	bottom: -20px;
          	left: 0;
          	width: 100%;
          	background-image: url('fancybox-x.png');
          	background-position: 0px -20px;
          }
          
          #fancy-bg-sw {
          	bottom: -20px;
          	left: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -142px;
          }
          
          #fancy-bg-w {
          	top: 0;
          	left: -20px;
          	height: 100%;
          	background-image: url('fancybox-y.png');
          }
          
          #fancy-bg-nw {
          	top: -20px;
          	left: -20px;
          	background-image: url('fancybox.png');
          	background-position: -40px -122px;
          }
          
          /* IE */
          
          #fancybox-loading.fancybox-ie div	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-close		{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); }
          
          .fancybox-ie #fancybox-title-over	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
          .fancybox-ie #fancybox-title-left	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-title-main	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-title-right	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); }
          
          .fancybox-ie #fancybox-left-ico		{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); }
          .fancybox-ie #fancybox-right-ico	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); }
          
          .fancybox-ie .fancy-bg { background: transparent !important; }
          
          .fancybox-ie #fancy-bg-n	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-ne	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-e	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-se	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-s	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-sw	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-w	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); }
          .fancybox-ie #fancy-bg-nw	{ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        19. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (418 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 28094
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"28094-1267813320000"
          Last-Modified: Fri, 05 Mar 2010 18:22:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (28094 bytes)
          /*
           * FancyBox - jQuery Plugin
           * Simple and fancy lightbox alternative
           *
           * Examples and documentation at: http://fancybox.net
           * 
           * Copyright (c) 2008 - 2010 Janis Skarnelis
           *
           * Version: 1.3.1 (05/03/2010)
           * Requires: jQuery v1.3+
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          	var tmp, loading, overlay, wrap, outer, inner, close, nav_left, nav_right,
          
          		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
          
          		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
          
          		loadingTimer, loadingFrame = 1,
          
          		start_pos, final_pos, busy = false, shadow = 20, fx = $.extend($('<div/>')[0], { prop: 0 }), titleh = 0, 
          
          		isIE6 = !$.support.opacity && !window.XMLHttpRequest,
          
          		/*
          		 * Private methods 
          		 */
          
          		fancybox_abort = function() {
          			loading.hide();
          
          			imgPreloader.onerror = imgPreloader.onload = null;
          
          			if (ajaxLoader) {
          				ajaxLoader.abort();
          			}
          
          			tmp.empty();
          		},
          
          		fancybox_error = function() {
          			$.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', {
          				'scrolling'		: 'no',
          				'padding'		: 20,
          				'transitionIn'	: 'none',
          				'transitionOut'	: 'none'
          			});
          		},
          
          		fancybox_get_viewport = function() {
          			return [ $(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ];
          		},
          
          		fancybox_get_zoom_to = function () {
          			var view	= fancybox_get_viewport(),
          				to		= {},
          
          				margin = currentOpts.margin,
          				resize = currentOpts.autoScale,
          
          				horizontal_space	= (shadow + margin) * 2,
          				vertical_space		= (shadow + margin) * 2,
          				double_padding		= (currentOpts.padding * 2),
          				
          				ratio;
          
          			if (currentOpts.width.toString().indexOf('%') > -1) {
          				to.width = ((view[0] * parseFloat(currentOpts.width)) / 100) - (shadow * 2) ;
          				resize = false;
          
          			} else {
          				to.width = currentOpts.width + double_padding;
          			}
          
          			if (currentOpts.height.toString().indexOf('%') > -1) {
          				to.height = ((view[1] * parseFloat(currentOpts.height)) / 100) - (shadow * 2);
          				resize = false;
          
          			} else {
          				to.height = currentOpts.height + double_padding;
          			}
          
          			if (resize && (to.width > (view[0] - horizontal_space) || to.height > (view[1] - vertical_space))) {
          				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
          					horizontal_space	+= double_padding;
          					vertical_space		+= double_padding;
          
          					ratio = Math.min(Math.min( view[0] - horizontal_space, currentOpts.width) / currentOpts.width, Math.min( view[1] - vertical_space, currentOpts.height) / currentOpts.height);
          
          					to.width	= Math.round(ratio * (to.width	- double_padding)) + double_padding;
          					to.height	= Math.round(ratio * (to.height	- double_padding)) + double_padding;
          
          				} else {
          					to.width	= Math.min(to.width,	(view[0] - horizontal_space));
          					to.height	= Math.min(to.height,	(view[1] - vertical_space));
          				}
          			}
          
          			to.top	= view[3] + ((view[1] - (to.height	+ (shadow * 2 ))) * 0.5);
          			to.left	= view[2] + ((view[0] - (to.width	+ (shadow * 2 ))) * 0.5);
          
          			if (currentOpts.autoScale === false) {
          				to.top	= Math.max(view[3] + margin, to.top);
          				to.left	= Math.max(view[2] + margin, to.left);
          			}
          
          			return to;
          		},
          
          		fancybox_format_title = function(title) {
          			if (title && title.length) {
          				switch (currentOpts.titlePosition) {
          					case 'inside':
          						return title;
          					case 'over':
          						return '<span id="fancybox-title-over">' + title + '</span>';
          					default:
          						return '<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">' + title + '</span><span id="fancybox-title-right"></span></span>';
          				}
          			}
          
          			return false;
          		},
          
          		fancybox_process_title = function() {
          			var title	= currentOpts.title,
          				width	= final_pos.width - (currentOpts.padding * 2),
          				titlec	= 'fancybox-title-' + currentOpts.titlePosition;
          				
          			$('#fancybox-title').remove();
          
          			titleh = 0;
          
          			if (currentOpts.titleShow === false) {
          				return;
          			}
          
          			title = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(title, currentArray, currentIndex, currentOpts) : fancybox_format_title(title);
          
          			if (!title || title === '') {
          				return;
          			}
          
          			$('<div id="fancybox-title" class="' + titlec + '" />').css({
          				'width'			: width,
          				'paddingLeft'	: currentOpts.padding,
          				'paddingRight'	: currentOpts.padding
          			}).html(title).appendTo('body');
          
          			switch (currentOpts.titlePosition) {
          				case 'inside':
          					titleh = $("#fancybox-title").outerHeight(true) - currentOpts.padding;
          					final_pos.height += titleh;
          				break;
          
          				case 'over':
          					$('#fancybox-title').css('bottom', currentOpts.padding);
          				break;
          
          				default:
          					$('#fancybox-title').css('bottom', $("#fancybox-title").outerHeight(true) * -1);
          				break;
          			}
          
          			$('#fancybox-title').appendTo( outer ).hide();
          		},
          
          		fancybox_set_navigation = function() {
          			$(document).unbind('keydown.fb').bind('keydown.fb', function(e) {
          				if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
          					e.preventDefault();
          					$.fancybox.close();
          
          				} else if (e.keyCode == 37) {
          					e.preventDefault();
          					$.fancybox.prev();
          
          				} else if (e.keyCode == 39) {
          					e.preventDefault();
          					$.fancybox.next();
          				}
          			});
          
          			if ($.fn.mousewheel) {
          				wrap.unbind('mousewheel.fb');
          
          				if (currentArray.length > 1) {
          					wrap.bind('mousewheel.fb', function(e, delta) {
          						e.preventDefault();
          
          						if (busy || delta === 0) {
          							return;
          						}
          
          						if (delta > 0) {
          							$.fancybox.prev();
          						} else {
          							$.fancybox.next();
          						}
          					});
          				}
          			}
          
          			if (!currentOpts.showNavArrows) { return; }
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
          				nav_left.show();
          			}
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
          				nav_right.show();
          			}
          		},
          
          		fancybox_preload_images = function() {
          			var href, 
          				objNext;
          				
          			if ((currentArray.length -1) > currentIndex) {
          				href = currentArray[ currentIndex + 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          
          			if (currentIndex > 0) {
          				href = currentArray[ currentIndex - 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          		},
          
          		_finish = function () {
          			inner.css('overflow', (currentOpts.scrolling == 'auto' ? (currentOpts.type == 'image' || currentOpts.type == 'iframe' || currentOpts.type == 'swf' ? 'hidden' : 'auto') : (currentOpts.scrolling == 'yes' ? 'auto' : 'visible')));
          
          			if (!$.support.opacity) {
          				inner.get(0).style.removeAttribute('filter');
          				wrap.get(0).style.removeAttribute('filter');
          			}
          
          			$('#fancybox-title').show();
          
          			if (currentOpts.hideOnContentClick)	{
          				inner.one('click', $.fancybox.close);
          			}
          			if (currentOpts.hideOnOverlayClick)	{
          				overlay.one('click', $.fancybox.close);
          			}
          
          			if (currentOpts.showCloseButton) {
          				close.show();
          			}
          
          			fancybox_set_navigation();
          
          			$(window).bind("resize.fb", $.fancybox.center);
          
          			if (currentOpts.centerOnScroll) {
          				$(window).bind("scroll.fb", $.fancybox.center);
          			} else {
          				$(window).unbind("scroll.fb");
          			}
          
          			if ($.isFunction(currentOpts.onComplete)) {
          				currentOpts.onComplete(currentArray, currentIndex, currentOpts);
          			}
          
          			busy = false;
          
          			fancybox_preload_images();
          		},
          
          		fancybox_draw = function(pos) {
          			var width	= Math.round(start_pos.width	+ (final_pos.width	- start_pos.width)	* pos),
          				height	= Math.round(start_pos.height	+ (final_pos.height	- start_pos.height)	* pos),
          
          				top		= Math.round(start_pos.top	+ (final_pos.top	- start_pos.top)	* pos),
          				left	= Math.round(start_pos.left	+ (final_pos.left	- start_pos.left)	* pos);
          
          			wrap.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px',
          				'top'		: top		+ 'px',
          				'left'		: left		+ 'px'
          			});
          
          			width	= Math.max(width - currentOpts.padding * 2, 0);
          			height	= Math.max(height - (currentOpts.padding * 2 + (titleh * pos)), 0);
          
          			inner.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px'
          			});
          
          			if (typeof final_pos.opacity !== 'undefined') {
          				wrap.css('opacity', (pos < 0.5 ? 0.5 : pos));
          			}
          		},
          
          		fancybox_get_obj_pos = function(obj) {
          			var pos		= obj.offset();
          
          			pos.top		+= parseFloat( obj.css('paddingTop') )	|| 0;
          			pos.left	+= parseFloat( obj.css('paddingLeft') )	|| 0;
          
          			pos.top		+= parseFloat( obj.css('border-top-width') )	|| 0;
          			pos.left	+= parseFloat( obj.css('border-left-width') )	|| 0;
          
          			pos.width	= obj.width();
          			pos.height	= obj.height();
          
          			return pos;
          		},
          
          		fancybox_get_zoom_from = function() {
          			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
          				from = {},
          				pos,
          				view;
          
          			if (orig && orig.length) {
          				pos = fancybox_get_obj_pos(orig);
          
          				from = {
          					width	: (pos.width	+ (currentOpts.padding * 2)),
          					height	: (pos.height	+ (currentOpts.padding * 2)),
          					top		: (pos.top		- currentOpts.padding - shadow),
          					left	: (pos.left		- currentOpts.padding - shadow)
          				};
          				
          			} else {
          				view = fancybox_get_viewport();
          
          				from = {
          					width	: 1,
          					height	: 1,
          					top		: view[3] + view[1] * 0.5,
          					left	: view[2] + view[0] * 0.5
          				};
          			}
          
          			return from;
          		},
          
          		fancybox_show = function() {
          			loading.hide();
          
          			if (wrap.is(":visible") && $.isFunction(currentOpts.onCleanup)) {
          				if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          					$.event.trigger('fancybox-cancel');
          
          					busy = false;
          					return;
          				}
          			}
          
          			currentArray	= selectedArray;
          			currentIndex	= selectedIndex;
          			currentOpts		= selectedOpts;
          
          			inner.get(0).scrollTop	= 0;
          			inner.get(0).scrollLeft	= 0;
          
          			if (currentOpts.overlayShow) {
          				if (isIE6) {
          					$('select:not(#fancybox-tmp select)').filter(function() {
          						return this.style.visibility !== 'hidden';
          					}).css({'visibility':'hidden'}).one('fancybox-cleanup', function() {
          						this.style.visibility = 'inherit';
          					});
          				}
          
          				overlay.css({
          					'background-color'	: currentOpts.overlayColor,
          					'opacity'			: currentOpts.overlayOpacity
          				}).unbind().show();
          			}
          
          			final_pos = fancybox_get_zoom_to();
          
          			fancybox_process_title();
          
          			if (wrap.is(":visible")) {
          				$( close.add( nav_left ).add( nav_right ) ).hide();
          
          				var pos = wrap.position(),
          					equal;
          
          				start_pos = {
          					top		:	pos.top ,
          					left	:	pos.left,
          					width	:	wrap.width(),
          					height	:	wrap.height()
          				};
          
          				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
          
          				inner.fadeOut(currentOpts.changeFade, function() {
          					var finish_resizing = function() {
          						inner.html( tmp.contents() ).fadeIn(currentOpts.changeFade, _finish);
          					};
          					
          					$.event.trigger('fancybox-change');
          
          					inner.empty().css('overflow', 'hidden');
          
          					if (equal) {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          						});
          						
          						finish_resizing();
          
          					} else {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          						});
          						
          						fx.prop = 0;
          
          						$(fx).animate({ prop: 1 }, {
          							 duration	: currentOpts.changeSpeed,
          							 easing		: currentOpts.easingChange,
          							 step		: fancybox_draw,
          							 complete	: finish_resizing
          						});
          					}
          				});
          
          				return;
          			}
          
          			wrap.css('opacity', 1);
          
          			if (currentOpts.transitionIn == 'elastic') {
          				start_pos = fancybox_get_zoom_from();
          
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css(start_pos).show();
          
          				if (currentOpts.opacity) {
          					final_pos.opacity = 0;
          				}
          
          				fx.prop = 0;
          
          				$(fx).animate({ prop: 1 }, {
          					 duration	: currentOpts.speedIn,
          					 easing		: currentOpts.easingIn,
          					 step		: fancybox_draw,
          					 complete	: _finish
          				});
          
          			} else {
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css( final_pos ).fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
          			}
          		},
          
          		fancybox_process_inline = function() {
          			tmp.width(	selectedOpts.width );
          			tmp.height(	selectedOpts.height );
          
          			if (selectedOpts.width	== 'auto') {
          				selectedOpts.width = tmp.width();
          			}
          			if (selectedOpts.height	== 'auto') {
          				selectedOpts.height	= tmp.height();
          			}
          
          			fancybox_show();
          		},
          		
          		fancybox_process_image = function() {
          			busy = true;
          
          			selectedOpts.width	= imgPreloader.width;
          			selectedOpts.height	= imgPreloader.height;
          
          			$("<img />").attr({
          				'id'	: 'fancybox-img',
          				'src'	: imgPreloader.src,
          				'alt'	: selectedOpts.title
          			}).appendTo( tmp );
          
          			fancybox_show();
          		},
          
          		fancybox_start = function() {
          			fancybox_abort();
          
          			var obj	= selectedArray[ selectedIndex ],
          				href, 
          				type, 
          				title,
          				str,
          				emb,
          				selector,
          				data;
          
          			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
          			title = obj.title || $(obj).title || selectedOpts.title || '';
          			
          			if (obj.nodeName && !selectedOpts.orig) {
          				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
          			}
          
          			if (title === '' && selectedOpts.orig) {
          				title = selectedOpts.orig.attr('alt');
          			}
          
          			if (obj.nodeName && (/^(?:javascript|#)/i).test(obj.href)) {
          				href = selectedOpts.href || null;
          			} else {
          				href = selectedOpts.href || obj.href || null;
          			}
          
          			if (selectedOpts.type) {
          				type = selectedOpts.type;
          
          				if (!href) {
          					href = selectedOpts.content;
          				}
          				
          			} else if (selectedOpts.content) {
          				type	= 'html';
          
          			} else if (href) {
          				if (href.match(imgRegExp)) {
          					type = 'image';
          
          				} else if (href.match(swfRegExp)) {
          					type = 'swf';
          
          				} else if ($(obj).hasClass("iframe")) {
          					type = 'iframe';
          
          				} else if (href.match(/#/)) {
          					obj = href.substr(href.indexOf("#"));
          
          					type = $(obj).length > 0 ? 'inline' : 'ajax';
          				} else {
          					type = 'ajax';
          				}
          			} else {
          				type = 'inline';
          			}
          
          			selectedOpts.type	= type;
          			selectedOpts.href	= href;
          			selectedOpts.title	= title;
          
          			if (selectedOpts.autoDimensions && selectedOpts.type !== 'iframe' && selectedOpts.type !== 'swf') {
          				selectedOpts.width		= 'auto';
          				selectedOpts.height		= 'auto';
          			}
          
          			if (selectedOpts.modal) {
          				selectedOpts.overlayShow		= true;
          				selectedOpts.hideOnOverlayClick	= false;
          				selectedOpts.hideOnContentClick	= false;
          				selectedOpts.enableEscapeButton	= false;
          				selectedOpts.showCloseButton	= false;
          			}
          
          			if ($.isFunction(selectedOpts.onStart)) {
          				if (selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts) === false) {
          					busy = false;
          					return;
          				}
          			}
          
          			tmp.css('padding', (shadow + selectedOpts.padding + selectedOpts.margin));
          
          			$('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
          				$(this).replaceWith(inner.children());
          			});
          
          			switch (type) {
          				case 'html' :
          					tmp.html( selectedOpts.content );
          					fancybox_process_inline();
          				break;
          
          				case 'inline' :
          					$('<div class="fancybox-inline-tmp" />').hide().insertBefore( $(obj) ).bind('fancybox-cleanup', function() {
          						$(this).replaceWith(inner.children());
          					}).bind('fancybox-cancel', function() {
          						$(this).replaceWith(tmp.children());
          					});
          
          					$(obj).appendTo(tmp);
          
          					fancybox_process_inline();
          				break;
          
          				case 'image':
          					busy = false;
          
          					$.fancybox.showActivity();
          
          					imgPreloader = new Image();
          
          					imgPreloader.onerror = function() {
          						fancybox_error();
          					};
          
          					imgPreloader.onload = function() {
          						imgPreloader.onerror = null;
          						imgPreloader.onload = null;
          						fancybox_process_image();
          					};
          
          					imgPreloader.src = href;
          		
          				break;
          
          				case 'swf':
          					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
          					emb = '';
          					
          					$.each(selectedOpts.swf, function(name, val) {
          						str += '<param name="' + name + '" value="' + val + '"></param>';
          						emb += ' ' + name + '="' + val + '"';
          					});
          
          					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
          
          					tmp.html(str);
          
          					fancybox_process_inline();
          				break;
          
          				case 'ajax':
          					selector	= href.split('#', 2);
          					data		= selectedOpts.ajax.data || {};
          
          					if (selector.length > 1) {
          						href = selector[0];
          
          						if (typeof data == "string") {
          							data += '&selector=' + selector[1];
          						} else {
          							data.selector = selector[1];
          						}
          					}
          
          					busy = false;
          					$.fancybox.showActivity();
          
          					ajaxLoader = $.ajax($.extend(selectedOpts.ajax, {
          						url		: href,
          						data	: data,
          						error	: fancybox_error,
          						success : function(data, textStatus, XMLHttpRequest) {
          							if (ajaxLoader.status == 200) {
          								tmp.html( data );
          								fancybox_process_inline();
          							}
          						}
          					}));
          
          				break;
          
          				case 'iframe' :
          					$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" scrolling="' + selectedOpts.scrolling + '" src="' + selectedOpts.href + '"></iframe>').appendTo(tmp);
          					fancybox_show();
          				break;
          			}
          		},
          
          		fancybox_animate_loading = function() {
          			if (!loading.is(':visible')){
          				clearInterval(loadingTimer);
          				return;
          			}
          
          			$('div', loading).css('top', (loadingFrame * -40) + 'px');
          
          			loadingFrame = (loadingFrame + 1) % 12;
          		},
          
          		fancybox_init = function() {
          			if ($("#fancybox-wrap").length) {
          				return;
          			}
          
          			$('body').append(
          				tmp			= $('<div id="fancybox-tmp"></div>'),
          				loading		= $('<div id="fancybox-loading"><div></div></div>'),
          				overlay		= $('<div id="fancybox-overlay"></div>'),
          				wrap		= $('<div id="fancybox-wrap"></div>')
          			);
          
          			if (!$.support.opacity) {
          				wrap.addClass('fancybox-ie');
          				loading.addClass('fancybox-ie');
          			}
          
          			outer = $('<div id="fancybox-outer"></div>')
          				.append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>')
          				.appendTo( wrap );
          
          			outer.append(
          				inner		= $('<div id="fancybox-inner"></div>'),
          				close		= $('<a id="fancybox-close"></a>'),
          
          				nav_left	= $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
          				nav_right	= $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
          			);
          
          			close.click($.fancybox.close);
          			loading.click($.fancybox.cancel);
          
          			nav_left.click(function(e) {
          				e.preventDefault();
          				$.fancybox.prev();
          			});
          
          			nav_right.click(function(e) {
          				e.preventDefault();
          				$.fancybox.next();
          			});
          
          			if (isIE6) {
          				overlay.get(0).style.setExpression('height',	"document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");
          				loading.get(0).style.setExpression('top',		"(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");
          
          				outer.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>');
          			}
          		};
          
          	/*
          	 * Public methods 
          	 */
          
          	$.fn.fancybox = function(options) {
          		$(this)
          			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
          			.unbind('click.fb').bind('click.fb', function(e) {
          				e.preventDefault();
          
          				if (busy) {
          					return;
          				}
          
          				busy = true;
          
          				$(this).blur();
          
          				selectedArray	= [];
          				selectedIndex	= 0;
          
          				var rel = $(this).attr('rel') || '';
          
          				if (!rel || rel == '' || rel === 'nofollow') {
          					selectedArray.push(this);
          
          				} else {
          					selectedArray	= $("a[rel=" + rel + "], area[rel=" + rel + "]");
          					selectedIndex	= selectedArray.index( this );
          				}
          
          				fancybox_start();
          
          				return false;
          			});
          
          		return this;
          	};
          
          	$.fancybox = function(obj) {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		var opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
          
          		selectedArray	= [];
          		selectedIndex	= opts.index || 0;
          
          		if ($.isArray(obj)) {
          			for (var i = 0, j = obj.length; i < j; i++) {
          				if (typeof obj[i] == 'object') {
          					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
          				} else {
          					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
          				}
          			}
          
          			selectedArray = jQuery.merge(selectedArray, obj);
          
          		} else {
          			if (typeof obj == 'object') {
          				$(obj).data('fancybox', $.extend({}, opts, obj));
          			} else {
          				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
          			}
          
          			selectedArray.push(obj);
          		}
          
          		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
          			selectedIndex = 0;
          		}
          
          		fancybox_start();
          	};
          
          	$.fancybox.showActivity = function() {
          		clearInterval(loadingTimer);
          
          		loading.show();
          		loadingTimer = setInterval(fancybox_animate_loading, 66);
          	};
          
          	$.fancybox.hideActivity = function() {
          		loading.hide();
          	};
          
          	$.fancybox.next = function() {
          		return $.fancybox.pos( currentIndex + 1);
          	};
          	
          	$.fancybox.prev = function() {
          		return $.fancybox.pos( currentIndex - 1);
          	};
          
          	$.fancybox.pos = function(pos) {
          		if (busy) {
          			return;
          		}
          
          		pos = parseInt(pos, 10);
          
          		if (pos > -1 && currentArray.length > pos) {
          			selectedIndex = pos;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos < 0) {
          			selectedIndex = currentArray.length - 1;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos >= currentArray.length) {
          			selectedIndex = 0;
          			fancybox_start();
          		}
          
          		return;
          	};
          
          	$.fancybox.cancel = function() {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		$.event.trigger('fancybox-cancel');
          
          		fancybox_abort();
          
          		if (selectedOpts && $.isFunction(selectedOpts.onCancel)) {
          			selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
          		}
          
          		busy = false;
          	};
          
          	// Note: within an iframe use - parent.$.fancybox.close();
          	$.fancybox.close = function() {
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		if (currentOpts && $.isFunction(currentOpts.onCleanup)) {
          			if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          				busy = false;
          				return;
          			}
          		}
          
          		fancybox_abort();
          
          		$(close.add( nav_left ).add( nav_right )).hide();
          
          		$('#fancybox-title').remove();
          
          		wrap.add(inner).add(overlay).unbind();
          
          		$(window).unbind("resize.fb scroll.fb");
          		$(document).unbind('keydown.fb');
          
          		function _cleanup() {
          			overlay.fadeOut('fast');
          
          			wrap.hide();
          
          			$.event.trigger('fancybox-cleanup');
          
          			inner.empty();
          
          			if ($.isFunction(currentOpts.onClosed)) {
          				currentOpts.onClosed(currentArray, currentIndex, currentOpts);
          			}
          
          			currentArray	= selectedOpts	= [];
          			currentIndex	= selectedIndex	= 0;
          			currentOpts		= selectedOpts	= {};
          
          			busy = false;
          		}
          
          		inner.css('overflow', 'hidden');
          
          		if (currentOpts.transitionOut == 'elastic') {
          			start_pos = fancybox_get_zoom_from();
          
          			var pos = wrap.position();
          
          			final_pos = {
          				top		:	pos.top ,
          				left	:	pos.left,
          				width	:	wrap.width(),
          				height	:	wrap.height()
          			};
          
          			if (currentOpts.opacity) {
          				final_pos.opacity = 1;
          			}
          
          			fx.prop = 1;
          
          			$(fx).animate({ prop: 0 }, {
          				 duration	: currentOpts.speedOut,
          				 easing		: currentOpts.easingOut,
          				 step		: fancybox_draw,
          				 complete	: _cleanup
          			});
          
          		} else {
          			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
          		}
          	};
          
          	$.fancybox.resize = function() {
          		var c, h;
          		
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		c = inner.wrapInner("<div style='overflow:auto'></div>").children();
          		h = c.height();
          
          		wrap.css({height:	h + (currentOpts.padding * 2) + titleh});
          		inner.css({height:	h});
          
          		c.replaceWith(c.children());
          
          		$.fancybox.center();
          	};
          
          	$.fancybox.center = function() {
          		busy = true;
          
          		var view	= fancybox_get_viewport(),
          			margin	= currentOpts.margin,
          			to		= {};
          
          		to.top	= view[3] + ((view[1] - ((wrap.height() - titleh) + (shadow * 2 ))) * 0.5);
          		to.left	= view[2] + ((view[0] - (wrap.width() + (shadow * 2 ))) * 0.5);
          
          		to.top	= Math.max(view[3] + margin, to.top);
          		to.left	= Math.max(view[2] + margin, to.left);
          
          		wrap.css(to);
          
          		busy = false;
          	};
          
          	$.fn.fancybox.defaults = {
          		padding				:	10,
          		margin				:	20,
          		opacity				:	false,
          		modal				:	false,
          		cyclic				:	false,
          		scrolling			:	'auto',	// 'auto', 'yes' or 'no'
          
          		width				:	560,
          		height				:	340,
          
          		autoScale			:	true,
          		autoDimensions		:	true,
          		centerOnScroll		:	false,
          
          		ajax				:	{},
          		swf					:	{ wmode: 'transparent' },
          
          		hideOnOverlayClick	:	true,
          		hideOnContentClick	:	false,
          
          		overlayShow			:	true,
          		overlayOpacity		:	0.3,
          		overlayColor		:	'#666',
          
          		titleShow			:	true,
          		titlePosition		:	'outside',	// 'outside', 'inside' or 'over'
          		titleFormat			:	null,
          
          		transitionIn		:	'fade',	// 'elastic', 'fade' or 'none'
          		transitionOut		:	'fade',	// 'elastic', 'fade' or 'none'
          
          		speedIn				:	300,
          		speedOut			:	300,
          
          		changeSpeed			:	300,
          		changeFade			:	'fast',
          
          		easingIn			:	'swing',
          		easingOut			:	'swing',
          
          		showCloseButton		:	true,
          		showNavArrows		:	true,
          		enableEscapeButton	:	true,
          
          		onStart				:	null,
          		onCancel			:	null,
          		onComplete			:	null,
          		onCleanup			:	null,
          		onClosed			:	null
          	};
          
          	$(document).ready(function() {
          		fancybox_init();
          	});
          
          })(jQuery);
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        20. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.form.min.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (381 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.form.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 14504
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"14504-1371572158000"
          Last-Modified: Tue, 18 Jun 2013 16:15:58 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (14504 bytes)
          /*
          * jQuery Form Plugin; v20130616
          * http://jquery.malsup.com/form/
          * Copyright (c) 2013 M. Alsup; Dual licensed: MIT/GPL
          * https://github.com/malsup/form#copyright-and-license
          */
          ;(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(this).ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=this;if(i.clk=r,"image"==r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n={};n.fileapi=void 0!==e("<input type='file'/>").get(0).files,n.formdata=void 0!==window.FormData;var i=!!e.fn.prop;e.fn.attr2=function(){if(!i)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t){function r(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;o>a;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function o(a){for(var n=new FormData,i=0;a.length>i;i++)n.append(a[i].name,a[i].value);if(t.extraData){var o=r(t.extraData);for(i=0;o.length>i;i++)o[i]&&n.append(o[i][0],o[i][1])}t.data=null;var s=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:u||"POST"});t.uploadProgress&&(s.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(100*(a/n))),t.uploadProgress(e,a,n,r)},!1),r}),s.data=null;var l=s.beforeSend;return s.beforeSend=function(e,t){t.data=n,l&&l.call(this,e,t)},e.ajax(s)}function s(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(r){a("cannot get iframe.contentWindow document: "+r)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function o(){function t(){try{var e=n(g).readyState;a("state = "+e),e&&"uninitialized"==e.toLowerCase()&&setTimeout(t,50)}catch(r){a("Server abort: ",r," (",r.name,")"),s(D),j&&clearTimeout(j),j=void 0}}var r=f.attr2("target"),i=f.attr2("action");w.setAttribute("target",d),u||w.setAttribute("method","POST"),i!=m.url&&w.setAttribute("action",m.url),m.skipEncodingOverride||u&&!/post/i.test(u)||f.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),m.timeout&&(j=setTimeout(function(){T=!0,s(k)},m.timeout));var o=[];try{if(m.extraData)for(var l in m.extraData)m.extraData.hasOwnProperty(l)&&(e.isPlainObject(m.extraData[l])&&m.extraData[l].hasOwnProperty("name")&&m.extraData[l].hasOwnProperty("value")?o.push(e('<input type="hidden" name="'+m.extraData[l].name+'">').val(m.extraData[l].value).appendTo(w)[0]):o.push(e('<input type="hidden" name="'+l+'">').val(m.extraData[l]).appendTo(w)[0]));m.iframeTarget||(v.appendTo("body"),g.attachEvent?g.attachEvent("onload",s):g.addEventListener("load",s,!1)),setTimeout(t,15);try{w.submit()}catch(c){var p=document.createElement("form").submit;p.apply(w)}}finally{w.setAttribute("action",i),r?w.setAttribute("target",r):f.removeAttr("target"),e(o).remove()}}function s(t){if(!x.aborted&&!F){if(M=n(g),M||(a("cannot access response document"),t=D),t===k&&x)return x.abort("timeout"),S.reject(x,"timeout"),void 0;if(t==D&&x)return x.abort("server abort"),S.reject(x,"error","server abort"),void 0;if(M&&M.location.href!=m.iframeSrc||T){g.detachEvent?g.detachEvent("onload",s):g.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"==m.dataType||M.XMLDocument||e.isXMLDoc(M);if(a("isXml="+o),!o&&window.opera&&(null===M.body||!M.body.innerHTML)&&--O)return a("requeing onLoad callback, DOM not available"),setTimeout(s,250),void 0;var u=M.body?M.body:M.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=M.XMLDocument?M.XMLDocument:M,o&&(m.dataType="xml"),x.getResponseHeader=function(e){var t={"content-type":m.dataType};return t[e]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var l=(m.dataType||"").toLowerCase(),c=/(json|script|text)/.test(l);if(c||m.textarea){var f=M.getElementsByTagName("textarea")[0];if(f)x.responseText=f.value,x.status=Number(f.getAttribute("status"))||x.status,x.statusText=f.getAttribute("statusText")||x.statusText;else if(c){var d=M.getElementsByTagName("pre")[0],h=M.getElementsByTagName("body")[0];d?x.responseText=d.textContent?d.textContent:d.innerText:h&&(x.responseText=h.textContent?h.textContent:h.innerText)}}else"xml"==l&&!x.responseXML&&x.responseText&&(x.responseXML=X(x.responseText));try{L=_(x,l,m)}catch(b){i="parsererror",x.error=r=b||i}}catch(b){a("error caught: ",b),i="error",x.error=r=b||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&300>x.status||304===x.status?"success":"error"),"success"===i?(m.success&&m.success.call(m.context,L,"success",x),S.resolve(x.responseText,"success",x),p&&e.event.trigger("ajaxSuccess",[x,m])):i&&(void 0===r&&(r=x.statusText),m.error&&m.error.call(m.context,x,i,r),S.reject(x,"error",r),p&&e.event.trigger("ajaxError",[x,m,r])),p&&e.event.trigger("ajaxComplete",[x,m]),p&&!--e.active&&e.event.trigger("ajaxStop"),m.complete&&m.complete.call(m.context,x,i),F=!0,m.timeout&&clearTimeout(j),setTimeout(function(){m.iframeTarget||v.remove(),x.responseXML=null},100)}}}var l,c,m,p,d,v,g,x,b,y,T,j,w=f[0],S=e.Deferred();if(r)for(c=0;h.length>c;c++)l=e(h[c]),i?l.prop("disabled",!1):l.removeAttr("disabled");if(m=e.extend(!0,{},e.ajaxSettings,t),m.context=m.context||m,d="jqFormIO"+(new Date).getTime(),m.iframeTarget?(v=e(m.iframeTarget),y=v.attr2("name"),y?d=y:v.attr2("name",d)):(v=e('<iframe name="'+d+'" src="'+m.iframeSrc+'" />'),v.css({position:"absolute",top:"-1000px",left:"-1000px"})),g=v[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{g.contentWindow.document.execCommand&&g.contentWindow.document.execCommand("Stop")}catch(n){}v.attr("src",m.iframeSrc),x.error=r,m.error&&m.error.call(m.context,x,r,t),p&&e.event.trigger("ajaxError",[x,m,r]),m.complete&&m.complete.call(m.context,x,r)}},p=m.global,p&&0===e.active++&&e.event.trigger("ajaxStart"),p&&e.event.trigger("ajaxSend",[x,m]),m.beforeSend&&m.beforeSend.call(m.context,x,m)===!1)return m.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;b=w.clk,b&&(y=b.name,y&&!b.disabled&&(m.extraData=m.extraData||{},m.extraData[y]=b.value,"image"==b.type&&(m.extraData[y+".x"]=w.clk_x,m.extraData[y+".y"]=w.clk_y)));var k=1,D=2,A=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&A&&(m.extraData=m.extraData||{},m.extraData[E]=A),m.forceSync?o():setTimeout(o,10);var L,M,F,O=50,X=e.parseXML||function(e,t){return window.ActiveXObject?(t=new ActiveXObject("Microsoft.XMLDOM"),t.async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!=t.documentElement.nodeName?t:null},C=e.parseJSON||function(e){return window.eval("("+e+")")},_=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i="xml"===r||!r&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&("json"===r||!r&&n.indexOf("json")>=0?o=C(o):("script"===r||!r&&n.indexOf("javascript")>=0)&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var u,l,c,f=this;"function"==typeof t&&(t={success:t}),u=t.type||this.attr2("method"),l=t.url||this.attr2("action"),c="string"==typeof l?e.trim(l):"",c=c||window.location.href||"",c&&(c=(c.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:c,success:e.ajaxSettings.success,type:u||"GET",iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&t.beforeSerialize(this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var p=t.traditional;void 0===p&&(p=e.ajaxSettings.traditional);var d,h=[],v=this.formToArray(t.semantic,h);if(t.data&&(t.extraData=t.data,d=e.param(t.data,p)),t.beforeSubmit&&t.beforeSubmit(v,this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[v,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var g=e.param(v,p);d&&(g=g?g+"&"+d:d),"GET"==t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+g,t.data=null):t.data=g;var x=[];if(t.resetForm&&x.push(function(){f.resetForm()}),t.clearForm&&x.push(function(){f.clearForm(t.includeHidden)}),!t.dataType&&t.target){var b=t.success||function(){};x.push(function(r){var a=t.replaceTarget?"replaceWith":"html";e(t.target)[a](r).each(b,arguments)})}else t.success&&x.push(t.success);if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=x.length;o>i;i++)x[i].apply(n,[e,r,a||f,f])},t.error){var y=t.error;t.error=function(e,r,a){var n=t.context||this;y.apply(n,[e,r,a,f])}}if(t.complete){var T=t.complete;t.complete=function(e,r){var a=t.context||this;T.apply(a,[e,r,f])}}var j=e('input[type=file]:enabled[value!=""]',this),w=j.length>0,S="multipart/form-data",k=f.attr("enctype")==S||f.attr("encoding")==S,D=n.fileapi&&n.formdata;a("fileAPI :"+D);var A,E=(w||k)&&!D;t.iframe!==!1&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){A=s(v)}):A=s(v):A=(w||k)&&D?o(v):e.ajax(t),f.removeData("jqxhr").data("jqxhr",A);for(var L=0;h.length>L;L++)h[L]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n){if(n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var i={s:this.selector,c:this.context};return!e.isReady&&i.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(i.s,i.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().bind("submit.form-plugin",n,t).bind("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.unbind("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r){var a=[];if(0===this.length)return a;var i=this[0],o=t?i.getElementsByTagName("*"):i.elements;if(!o)return a;var s,u,l,c,f,m,p;for(s=0,m=o.length;m>s;s++)if(f=o[s],l=f.name,l&&!f.disabled)if(t&&i.clk&&"image"==f.type)i.clk==f&&(a.push({name:l,value:e(f).val(),type:f.type}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}));else if(c=e.fieldValue(f,!0),c&&c.constructor==Array)for(r&&r.push(f),u=0,p=c.length;p>u;u++)a.push({name:l,value:c[u]});else if(n.fileapi&&"file"==f.type){r&&r.push(f);var d=f.files;if(d.length)for(u=0;d.length>u;u++)a.push({name:l,value:d[u],type:f.type});else a.push({name:l,value:"",type:f.type})}else null!==c&&c!==void 0&&(r&&r.push(f),a.push({name:l,value:c,type:f.type,required:f.required}));if(!t&&i.clk){var h=e(i.clk),v=h[0];l=v.name,l&&!v.disabled&&"image"==v.type&&(a.push({name:l,value:h.val()}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}))}return a},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor==Array)for(var i=0,o=n.length;o>i;i++)r.push({name:a,value:n[i]});else null!==n&&n!==void 0&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;n>a;a++){var i=this[a],o=e.fieldValue(i,t);null===o||void 0===o||o.constructor==Array&&!o.length||(o.constructor==Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,n=t.type,i=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"==n||"button"==n||("checkbox"==n||"radio"==n)&&!t.checked||("submit"==n||"image"==n)&&t.form&&t.form.clk!=t||"select"==i&&-1==t.selectedIndex))return null;if("select"==i){var o=t.selectedIndex;if(0>o)return null;for(var s=[],u=t.options,l="select-one"==n,c=l?o+1:u.length,f=l?o:0;c>f;f++){var m=u[f];if(m.selected){var p=m.value;if(p||(p=m.attributes&&m.attributes.value&&!m.attributes.value.specified?m.text:m.value),l)return p;s.push(p)}}return s}return e(t).val()},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"==n?this.value="":"checkbox"==a||"radio"==a?this.checked=!1:"select"==n?this.selectedIndex=-1:"file"==a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(t===!0&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")})},e.fn.resetForm=function(){return this.each(function(){("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset()})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"==r||"radio"==r)this.checked=t;else if("option"==this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"==a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1})(jQuery);
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        21. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (379 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 82920
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"82920-1230357900000"
          Last-Modified: Sat, 27 Dec 2008 06:05:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (82920 bytes)
          /*
           * jquery.layout 1.2.0
           *
           * Copyright (c) 2008 
           *   Fabrizio Balliano (http://www.fabrizioballiano.net)
           *   Kevin Dalman (http://allpro.net)
           *
           * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
           * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
           *
           * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
           * $Rev: 203 $
           * 
           * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
           */
          (function($) {
          
          $.fn.layout = function (opts) {
          
          /*
           * ###########################
           *   WIDGET CONFIG & OPTIONS
           * ###########################
           */
          
          	// DEFAULTS for options
          	var 
          		prefix = "ui-layout-" // prefix for ALL selectors and classNames
          	,	defaults = { //	misc default values
          			paneClass:				prefix+"pane"		// ui-layout-pane
          		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
          		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
          		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
          		,	buttonClass:			prefix+"button"		// ui-layout-button
          		,	contentSelector:		"."+prefix+"content"// ui-layout-content
          		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
          		}
          	;
          
          	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
          	var options = {
          		name:						""			// FUTURE REFERENCE - not used right now
          	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
          	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
          			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
          		,	closable:				true		// pane can open & close
          		,	resizable:				true		// when open, pane can be resized 
          		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
          		//,	paneSelector:			[ ]			// MUST be pane-specific!
          		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
          		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
          		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
          		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
          		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
          		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
          		,	resizerDragOpacity:		1			// option for ui.draggable
          		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
          		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
          		//,	size:					100			// inital size of pane - defaults are set 'per pane'
          		,	minSize:				0			// when manually resizing a pane
          		,	maxSize:				0			// ditto, 0 = no limit
          		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
          		,	spacing_closed:			6			// ditto - when pane is 'closed'
          		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
          		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
          		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
          		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
          		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
          		,	togglerTip_closed:		"Open"		// ditto
          		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
          		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
          		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
          		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
          		,	slideTrigger_close:		"mouseout"	// click, mouseout
          		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
          		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
          		,	togglerContent_closed:	""			// ditto
          		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
          		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
          		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
          		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
          		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
          		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
          		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
          		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
          		,	initClosed:				false		// true = init pane as 'closed'
          		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
          		
          		/*	callback options do not have to be set - listed here for reference only
          		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
          		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
          		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
          		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
          		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
          		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
          		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
          		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
          		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
          		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
          		*/
          		}
          	,	north: {
          			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
          		,	size:					"auto"
          		,	resizerCursor:			"n-resize"
          		}
          	,	south: {
          			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
          		,	size:					"auto"
          		,	resizerCursor:			"s-resize"
          		}
          	,	east: {
          			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
          		,	size:					200
          		,	resizerCursor:			"e-resize"
          		}
          	,	west: {
          			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
          		,	size:					200
          		,	resizerCursor:			"w-resize"
          		}
          	,	center: {
          			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
          		}
          
          	};
          
          
          	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
          		slide:	{
          			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	drop:	{
          			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	scale:	{
          			all:	{ duration:  "fast"	}
          		}
          	};
          
          
          	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
          	var config = {
          		allPanes:		"north,south,east,west,center"
          	,	borderPanes:	"north,south,east,west"
          	,	zIndex: { // set z-index values here
          			resizer_normal:	1		// normal z-index for resizer-bars
          		,	pane_normal:	2		// normal z-index for panes
          		,	mask:			4		// overlay div used to mask pane(s) during resizing
          		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
          		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
          		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
          		}
          	,	resizers: {
          			cssReq: {
          				position: 	"absolute"
          			,	padding: 	0
          			,	margin: 	0
          			,	fontSize:	"1px"
          			,	textAlign:	"left" // to counter-act "center" alignment!
          			,	overflow: 	"hidden" // keep toggler button from overflowing
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#DDD"
          			,	border:		"none"
          			}
          		}
          	,	togglers: {
          			cssReq: {
          				position: 	"absolute"
          			,	display: 	"block"
          			,	padding: 	0
          			,	margin: 	0
          			,	overflow:	"hidden"
          			,	textAlign:	"center"
          			,	fontSize:	"1px"
          			,	cursor: 	"pointer"
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#AAA"
          			}
          		}
          	,	content: {
          			cssReq: {
          				overflow:	"auto"
          			}
          		,	cssDef: {}
          		}
          	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
          			cssReq: {
          				position: 	"absolute"
          			,	margin:		0
          			,	zIndex: 	2
          			}
          		,	cssDef: {
          				padding:	"10px"
          			,	background:	"#FFF"
          			,	border:		"1px solid #BBB"
          			,	overflow:	"auto"
          			}
          		}
          	,	north: {
          			edge:			"top"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		0
          			,	bottom: 	"auto"
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	south: {
          			edge:			"bottom"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		"auto"
          			,	bottom: 	0
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	east: {
          			edge:			"right"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		"auto"
          			,	right: 		0
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	west: {
          			edge:			"left"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		0
          			,	right: 		"auto"
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	center: {
          			dir:			"center"
          		,	cssReq: {
          				left: 		"auto" // DYNAMIC
          			,	right: 		"auto" // DYNAMIC
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			,	width: 		"auto"
          			}
          		}
          	};
          
          
          	// DYNAMIC DATA
          	var state = {
          		// generate random 'ID#' to identify layout - used to create global namespace for timers
          		id:			Math.floor(Math.random() * 10000)
          	,	container:	{}
          	,	north:		{}
          	,	south:		{}
          	,	east:		{}
          	,	west:		{}
          	,	center:		{}
          	};
          
          
          	var 
          		altEdge = {
          			top:	"bottom"
          		,	bottom: "top"
          		,	left:	"right"
          		,	right:	"left"
          		}
          	,	altSide = {
          			north:	"south"
          		,	south:	"north"
          		,	east: 	"west"
          		,	west: 	"east"
          		}
          	;
          
          
          /*
           * ###########################
           *  INTERNAL HELPER FUNCTIONS
           * ###########################
           */
          
          	/**
          	 * isStr
          	 *
          	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
          	 */
          	var isStr = function (o) {
          		if (typeof o == "string")
          			return true;
          		else if (typeof o == "object") {
          			try {
          				var match = o.constructor.toString().match(/string/i); 
          				return (match !== null);
          			} catch (e) {} 
          		}
          		return false;
          	};
          
          	/**
          	 * str
          	 *
          	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
          	 *  else returns the original object
          	 */
          	var str = function (o) {
          		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
          		else return o;
          	};
          
          	/**
          	 * min / max
          	 *
          	 * Alias for Math.min/.max to simplify coding
          	 */
          	var min = function (x,y) { return Math.min(x,y); };
          	var max = function (x,y) { return Math.max(x,y); };
          
          	/**
          	 * transformData
          	 *
          	 * Processes the options passed in and transforms them into the format used by layout()
          	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
          	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
          	 * To update effects, options MUST use nested-keys format, with an effects key
          	 *
          	 * @callers  initOptions()
          	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
          	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
          	 */
          	var transformData = function (d) {
          		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
          		d = d || {};
          		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
          			json = $.extend( json, d ); // already in json format - add to base keys
          		else
          			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
          			$.each( d, function (key,val) {
          				a = key.split("__");
          				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
          			});
          		return json;
          	};
          
          	/**
          	 * setFlowCallback
          	 *
          	 * Set an INTERNAL callback to avoid simultaneous animation
          	 * Runs only if needed and only if all callbacks are not 'already set'!
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var setFlowCallback = function (action, pane, param) {
          		var
          			cb = action +","+ pane +","+ (param ? 1 : 0)
          		,	cP, cbPane
          		;
          		$.each(c.borderPanes.split(","), function (i,p) {
          			if (c[p].isMoving) {
          				bindCallback(p); // TRY to bind a callback
          				return false; // BREAK
          			}
          		});
          
          		function bindCallback (p, test) {
          			cP = c[p];
          			if (!cP.doCallback) {
          				cP.doCallback = true;
          				cP.callback = cb;
          			}
          			else { // try to 'chain' this callback
          				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
          				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
          					bindCallback (cpPane, true); // RECURSE
          			}
          		}
          	};
          
          	/**
          	 * execFlowCallback
          	 *
          	 * RUN the INTERNAL callback for this pane - if one exists
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var execFlowCallback = function (pane) {
          		var cP = c[pane];
          
          		// RESET flow-control flaGs
          		c.isLayoutBusy = false;
          		delete cP.isMoving;
          		if (!cP.doCallback || !cP.callback) return;
          
          		cP.doCallback = false; // RESET logic flag
          
          		// EXECUTE the callback
          		var
          			cb = cP.callback.split(",")
          		,	param = (cb[2] > 0 ? true : false)
          		;
          		if (cb[0] == "open")
          			open( cb[1], param  );
          		else if (cb[0] == "close")
          			close( cb[1], param );
          
          		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
          	};
          
          	/**
          	 * execUserCallback
          	 *
          	 * Executes a Callback function after a trigger event, like resize, open or close
          	 *
          	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
          	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
          	 */
          	var execUserCallback = function (pane, v_fn) {
          		if (!v_fn) return;
          		var fn;
          		try {
          			if (typeof v_fn == "function")
          				fn = v_fn;	
          			else if (typeof v_fn != "string")
          				return;
          			else if (v_fn.indexOf(",") > 0) {
          				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
          				var
          					args = v_fn.split(",")
          				,	fn = eval(args[0])
          				;
          				if (typeof fn=="function" && args.length > 1)
          					return fn(args[1]); // pass the argument parsed from 'list'
          			}
          			else // just the name of an external function?
          				fn = eval(v_fn);
          
          			if (typeof fn=="function")
          				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
          				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
          		}
          		catch (ex) {}
          	};
          
          	/**
          	 * cssNum
          	 *
          	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
          	 *
          	 * @callers  Called by many methods
          	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
          	 * @param String  property  The name of the CSS property, eg: top, width, etc.
          	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
          	 */
          	var cssNum = function ($E, prop) {
          		var
          			val = 0
          		,	hidden = false
          		,	visibility = ""
          		;
          		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
          			if ($.curCSS($E[0], "display", true) == "none") {
          				hidden = true;
          				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
          				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
          			}
          		}
          
          		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
          
          		if (hidden) { // WAS hidden, so put back the way it was
          			$E.css({ display: "none" });
          			if (visibility && visibility != "hidden")
          				$E.css({ visibility: visibility }); // reset 'visibility'
          		}
          
          		return val;
          	};
          
          	/**
          	 * cssW / cssH / cssSize
          	 *
          	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
          	 *
          	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
          	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
          	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
          	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
          	 *
          	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
          	 */
          	var cssW = function (e, outerWidth) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerWidth <= 0)
          			return 0;
          		else if (!(outerWidth>0))
          			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
          
          		if (!$.boxModel)
          			return outerWidth;
          
          		else // strip border and padding size from outerWidth to get CSS Width
          			return outerWidth
          				- cssNum($E, "paddingLeft")		
          				- cssNum($E, "paddingRight")
          				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
          				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
          			;
          	};
          	var cssH = function (e, outerHeight) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerHeight <= 0)
          			return 0;
          		else if (!(outerHeight>0))
          			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
          
          		if (!$.boxModel)
          			return outerHeight;
          
          		else // strip border and padding size from outerHeight to get CSS Height
          			return outerHeight
          				- cssNum($E, "paddingTop")
          				- cssNum($E, "paddingBottom")
          				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
          				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
          			;
          	};
          	var cssSize = function (pane, outerSize) {
          		if (c[pane].dir=="horz") // pane = north or south
          			return cssH(pane, outerSize);
          		else // pane = east or west
          			return cssW(pane, outerSize);
          	};
          
          	/**
          	 * getPaneSize
          	 *
          	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
          	 *
          	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
          	 */
          	var getPaneSize = function (pane, inclSpace) {
          		var 
          			$P	= $Ps[pane]
          		,	o	= options[pane]
          		,	s	= state[pane]
          		,	oSp	= (inclSpace ? o.spacing_open : 0)
          		,	cSp	= (inclSpace ? o.spacing_closed : 0)
          		;
          		if (!$P || s.isHidden)
          			return 0;
          		else if (s.isClosed || (s.isSliding && inclSpace))
          			return cSp;
          		else if (c[pane].dir == "horz")
          			return $P.outerHeight() + oSp;
          		else // dir == "vert"
          			return $P.outerWidth() + oSp;
          	};
          
          	var setPaneMinMaxSizes = function (pane) {
          		var 
          			d				= cDims
          		,	edge			= c[pane].edge
          		,	dir				= c[pane].dir
          		,	o				= options[pane]
          		,	s				= state[pane]
          		,	$P				= $Ps[pane]
          		,	$altPane		= $Ps[ altSide[pane] ]
          		,	paneSpacing		= o.spacing_open
          		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
          		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
          		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
          		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
          		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
          		,	minSize			= s.minSize || 0
          		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
          		,	minPos, maxPos	// used to set resizing limits
          		;
          		switch (pane) {
          			case "north":	minPos = d.offsetTop + minSize;
          							maxPos = d.offsetTop + maxSize;
          							break;
          			case "west":	minPos = d.offsetLeft + minSize;
          							maxPos = d.offsetLeft + maxSize;
          							break;
          			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
          							maxPos = d.offsetTop + d.innerHeight - minSize;
          							break;
          			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
          							maxPos = d.offsetLeft + d.innerWidth - minSize;
          							break;
          		}
          		// save data to pane-state
          		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
          	};
          
          	/**
          	 * getPaneDims
          	 *
          	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
          	 *
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
          	 */
          	var getPaneDims = function () {
          		var d = {
          			top:	getPaneSize("north", true) // true = include 'spacing' value for p
          		,	bottom:	getPaneSize("south", true)
          		,	left:	getPaneSize("west", true)
          		,	right:	getPaneSize("east", true)
          		,	width:	0
          		,	height:	0
          		};
          
          		with (d) {
          			width 	= cDims.innerWidth - left - right;
          			height 	= cDims.innerHeight - bottom - top;
          			// now add the 'container border/padding' to get final positions - relative to the container
          			top		+= cDims.top;
          			bottom	+= cDims.bottom;
          			left	+= cDims.left;
          			right	+= cDims.right;
          		}
          
          		return d;
          	};
          
          
          	/**
          	 * getElemDims
          	 *
          	 * Returns data for setting size of an element (container or a pane).
          	 *
          	 * @callers  create(), onWindowResize() for container, plus others for pane
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
          	 */
          	var getElemDims = function ($E) {
          		var
          			d = {} // dimensions hash
          		,	e, b, p // edge, border, padding
          		;
          
          		$.each("Left,Right,Top,Bottom".split(","), function () {
          			e = str(this);
          			b = d["border" +e] = cssNum($E, "border"+e+"Width");
          			p = d["padding"+e] = cssNum($E, "padding"+e);
          			d["offset" +e] = b + p; // total offset of content from outer edge
          			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
          			if ($E == $Container)
          				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
          		});
          
          		d.innerWidth  = d.outerWidth  = $E.outerWidth();
          		d.innerHeight = d.outerHeight = $E.outerHeight();
          		if ($.boxModel) {
          			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
          			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
          		}
          
          		return d;
          	};
          
          
          	var setTimer = function (pane, action, fn, ms) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) return; // timer already set!
          		else Timers[name] = setTimeout(fn, ms);
          	};
          
          	var clearTimer = function (pane, action) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) {
          			clearTimeout( Timers[name] );
          			delete Timers[name];
          			return true;
          		}
          		else
          			return false;
          	};
          
          
          /*
           * ###########################
           *   INITIALIZATION METHODS
           * ###########################
           */
          
          	/**
          	 * create
          	 *
          	 * Initialize the layout - called automatically whenever an instance of layout is created
          	 *
          	 * @callers  NEVER explicity called
          	 * @returns  An object pointer to the instance created
          	 */
          	var create = function () {
          		// initialize config/options
          		initOptions();
          
          		// initialize all objects
          		initContainer();	// set CSS as needed and init state.container dimensions
          		initPanes();		// size & position all panes
          		initHandles();		// create and position all resize bars & togglers buttons
          		initResizable();	// activate resizing on all panes where resizable=true
          		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
          
          		if (options.scrollToBookmarkOnLoad)
          			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
          
          		// bind hotkey function - keyDown - if required
          		initHotkeys();
          
          		// bind resizeAll() for 'this layout instance' to window.resize event
          		$(window).resize(function () {
          			var timerID = "timerLayout_"+state.id;
          			if (window[timerID]) clearTimeout(window[timerID]);
          			window[timerID] = null;
          			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
          				window[timerID] = setTimeout(resizeAll, 100);
          			else // most other browsers have a built-in delay before firing the resize event
          				resizeAll(); // resize all layout elements NOW!
          		});
          	};
          
          	/**
          	 * initContainer
          	 *
          	 * Validate and initialize container CSS and events
          	 *
          	 * @callers  create()
          	 */
          	var initContainer = function () {
          		try { // format html/body if this is a full page layout
          			if ($Container[0].tagName == "BODY") {
          				$("html").css({
          					height:		"100%"
          				,	overflow:	"hidden"
          				});
          				$("body").css({
          					position:	"relative"
          				,	height:		"100%"
          				,	overflow:	"hidden"
          				,	margin:		0
          				,	padding:	0		// TODO: test whether body-padding could be handled?
          				,	border:		"none"	// a body-border creates problems because it cannot be measured!
          				});
          			}
          			else { // set required CSS - overflow and position
          				var
          					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
          				,	p	= $Container.css("position")
          				,	h	= $Container.css("height")
          				;
          				// if this is a NESTED layout, then outer-pane ALREADY has position and height
          				if (!$Container.hasClass("ui-layout-pane")) {
          					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
          						CSS.position = "relative"; // container MUST have a 'position'
          					if (!h || h=="auto")
          						CSS.height = "100%"; // container MUST have a 'height'
          				}
          				$Container.css( CSS );
          			}
          		} catch (ex) {}
          
          		// get layout-container dimensions (updated when necessary)
          		cDims = state.container = getElemDims( $Container ); // update data-pointer too
          	};
          
          	/**
          	 * initHotkeys
          	 *
          	 * Bind layout hotkeys - if options enabled
          	 *
          	 * @callers  create()
          	 */
          	var initHotkeys = function () {
          		// bind keyDown to capture hotkeys, if option enabled for ANY pane
          		$.each(c.borderPanes.split(","), function (i,pane) {
          			var o = options[pane];
          			if (o.enableCursorHotkey || o.customHotkey) {
          				$(document).keydown( keyDown ); // only need to bind this ONCE
          				return false; // BREAK - binding was done
          			}
          		});
          	};
          
          	/**
          	 * initOptions
          	 *
          	 * Build final CONFIG and OPTIONS data
          	 *
          	 * @callers  create()
          	 */
          	var initOptions = function () {
          		// simplify logic by making sure passed 'opts' var has basic keys
          		opts = transformData( opts );
          
          		// update default effects, if case user passed key
          		if (opts.effects) {
          			$.extend( effects, opts.effects );
          			delete opts.effects;
          		}
          
          		// see if any 'global options' were specified
          		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
          			if (opts[key] !== undefined)
          				options[key] = opts[key];
          			else if (opts.defaults[key] !== undefined) {
          				options[key] = opts.defaults[key];
          				delete opts.defaults[key];
          			}
          		});
          
          		// remove any 'defaults' that MUST be set 'per-pane'
          		$.each("paneSelector,resizerCursor,customHotkey".split(","),
          			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
          		);
          
          		// now update options.defaults
          		$.extend( options.defaults, opts.defaults );
          		// make sure required sub-keys exist
          		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
          
          		// merge all config & options for the 'center' pane
          		c.center = $.extend( true, {}, c.defaults, c.center );
          		$.extend( options.center, opts.center );
          		// Most 'default options' do not apply to 'center', so add only those that DO
          		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
          		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
          			function (idx,key) { options.center[key] = o_Center[key]; }
          		);
          
          		var defs = options.defaults;
          
          		// create a COMPLETE set of options for EACH border-pane
          		$.each(c.borderPanes.split(","), function(i,pane) {
          			// apply 'pane-defaults' to CONFIG.PANE
          			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
          			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
          			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
          
          			// make sure we have base-classes
          			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
          			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
          			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
          
          			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
          			$.each(["_open","_close",""], function (i,n) { 
          				var
          					sName		= "fxName"+n
          				,	sSpeed		= "fxSpeed"+n
          				,	sSettings	= "fxSettings"+n
          				;
          				// recalculate fxName according to specificity rules
          				o[sName] =
          					opts[pane][sName]		// opts.west.fxName_open
          				||	opts[pane].fxName		// opts.west.fxName
          				||	opts.defaults[sName]	// opts.defaults.fxName_open
          				||	opts.defaults.fxName	// opts.defaults.fxName
          				||	o[sName]				// options.west.fxName_open
          				||	o.fxName				// options.west.fxName
          				||	defs[sName]				// options.defaults.fxName_open
          				||	defs.fxName				// options.defaults.fxName
          				||	"none"
          				;
          				// validate fxName to be sure is a valid effect
          				var fxName = o[sName];
          				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
          					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
          				// set vars for effects subkeys to simplify logic
          				var
          					fx = effects[fxName]	|| {} // effects.slide
          				,	fx_all	= fx.all		|| {} // effects.slide.all
          				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
          				;
          				// RECREATE the fxSettings[_open|_close] keys using specificity rules
          				o[sSettings] = $.extend(
          					{}
          				,	fx_all						// effects.slide.all
          				,	fx_pane						// effects.slide.west
          				,	defs.fxSettings || {}		// options.defaults.fxSettings
          				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
          				,	o.fxSettings				// options.west.fxSettings
          				,	o[sSettings]				// options.west.fxSettings_open
          				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
          				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
          				,	opts[pane].fxSettings		// opts.west.fxSettings
          				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
          				);
          				// recalculate fxSpeed according to specificity rules
          				o[sSpeed] =
          					opts[pane][sSpeed]		// opts.west.fxSpeed_open
          				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
          				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
          				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
          				||	o[sSpeed]				// options.west.fxSpeed_open
          				||	o[sSettings].duration	// options.west.fxSettings_open.duration
          				||	o.fxSpeed				// options.west.fxSpeed
          				||	o.fxSettings.duration	// options.west.fxSettings.duration
          				||	defs.fxSpeed			// options.defaults.fxSpeed
          				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
          				||	fx_pane.duration		// effects.slide.west.duration
          				||	fx_all.duration			// effects.slide.all.duration
          				||	"normal"				// DEFAULT
          				;
          				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
          			});
          		});
          	};
          
          	/**
          	 * initPanes
          	 *
          	 * Initialize module objects, styling, size and position for all panes
          	 *
          	 * @callers  create()
          	 */
          	var initPanes = function () {
          		// NOTE: do north & south FIRST so we can measure their height - do center LAST
          		$.each(c.allPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	fx		= s.fx
          			,	dir		= c[pane].dir
          			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
          			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
          			,	minSize	= o.minSize || 1
          			,	maxSize	= o.maxSize || 9999
          			,	spacing	= o.spacing_open || 0
          			,	sel		= o.paneSelector
          			,	isIE6	= ($.browser.msie && $.browser.version < 7)
          			,	CSS		= {}
          			,	$P, $C
          			;
          			$Cs[pane] = false; // init
          
          			if (sel.substr(0,1)==="#") // ID selector
          				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
          				$P = $Ps[pane] = $Container.find(sel+":first");
          			else { // class or other selector
          				$P = $Ps[pane] = $Container.children(sel+":first");
          				// look for the pane nested inside a 'form' element
          				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
          			}
          
          			if (!$P.length) {
          				$Ps[pane] = false; // logic
          				return true; // SKIP to next
          			}
          
          			// add basic classes & attributes
          			$P
          				.attr("pane", pane) // add pane-identifier
          				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
          			;
          
          			// init pane-logic vars, etc.
          			if (pane != "center") {
          				s.isClosed  = false; // true = pane is closed
          				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
          				s.isResizing= false; // true = pane is in process of being resized
          				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
          				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
          				// create special keys for internal use
          				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
          			}
          
          			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
          			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
          			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
          			CSS = {};	// reset var
          
          			// set css-position to account for container borders & padding
          			switch (pane) {
          				case "north": 	CSS.top 	= cDims.top;
          								CSS.left 	= cDims.left;
          								CSS.right	= cDims.right;
          								break;
          				case "south": 	CSS.bottom	= cDims.bottom;
          								CSS.left 	= cDims.left;
          								CSS.right 	= cDims.right;
          								break;
          				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
          								break;
          				case "east": 	CSS.right 	= cDims.right; // ditto
          								break;
          				case "center":	// top, left, width & height set by sizeMidPanes()
          			}
          
          			if (dir == "horz") { // north or south pane
          				if (size === 0 || size == "auto") {
          					$P.css({ height: "auto" });
          					size = $P.outerHeight();
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerHeight - spacing);
          				CSS.height = max(1, cssH(pane, size));
          				s.size = size; // update state
          				// make sure minSize is sufficient to avoid errors
          				s.maxSize = maxSize; // init value
          				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
          				// handle IE6
          				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
          				$P.css(CSS); // apply size & position
          			}
          			else if (dir == "vert") { // east or west pane
          				if (size === 0 || size == "auto") {
          					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
          					size = $P.outerWidth();
          					$P.css({ float: "none" }); // RESET
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerWidth - spacing);
          				CSS.width = max(1, cssW(pane, size));
          				s.size = size; // update state
          				s.maxSize = maxSize; // init value
          				// make sure minSize is sufficient to avoid errors
          				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
          				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
          				sizeMidPanes(pane, null, true); // true = onInit
          			}
          			else if (pane == "center") {
          				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
          				sizeMidPanes("center", null, true); // true = onInit
          			}
          
          			// close or hide the pane if specified in settings
          			if (o.initClosed && o.closable) {
          				$P.hide().addClass("closed");
          				s.isClosed = true;
          			}
          			else if (o.initHidden || o.initClosed) {
          				hide(pane, true); // will be completely invisible - no resizer or spacing
          				s.isHidden = true;
          			}
          			else
          				$P.addClass("open");
          
          			// check option for auto-handling of pop-ups & drop-downs
          			if (o.showOverflowOnHover)
          				$P.hover( allowOverflow, resetOverflow );
          
          			/*
          			 *	see if this pane has a 'content element' that we need to auto-size
          			 */
          			if (o.contentSelector) {
          				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
          				if (!$C.length) {
          					$Cs[pane] = false;
          					return true; // SKIP to next
          				}
          				$C.css( c.content.cssReq );
          				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
          				// NO PANE-SCROLLING when there is a content-div
          				$P.css({ overflow: "hidden" });
          			}
          		});
          	};
          
          	/**
          	 * initHandles
          	 *
          	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
          	 *
          	 * @callers  create()
          	 */
          	var initHandles = function () {
          		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	rClass	= o.resizerClass
          			,	tClass	= o.togglerClass
          			,	$P		= $Ps[pane]
          			;
          			$Rs[pane] = false; // INIT
          			$Ts[pane] = false;
          
          			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
          
          			var 
          				edge	= c[pane].edge
          			,	isOpen	= $P.is(":visible")
          			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
          			,	_pane	= "-"+ pane // used for classNames
          			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
          			,	$R, $T
          			;
          			// INIT RESIZER BAR
          			$R = $Rs[pane] = $("<span></span>");
          	
          			if (isOpen && o.resizable)
          				; // this is handled by initResizable
          			else if (!isOpen && o.slidable)
          				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
          	
          			$R
          				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
          				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
          				.attr("resizer", pane) // so we can read this from the resizer
          				.css(c.resizers.cssReq) // add base/required styles
          				// POSITION of resizer bar - allow for container border & padding
          				.css(edge, cDims[edge] + getPaneSize(pane))
          				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
          				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
          				.appendTo($Container) // append DIV to container
          			;
          			 // ADD VISUAL STYLES
          			if (o.applyDefaultStyles)
          				$R.css(c.resizers.cssDef);
          
          			if (o.closable) {
          				// INIT COLLAPSER BUTTON
          				$T = $Ts[pane] = $("<div></div>");
          				$T
          					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
          					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
          					.css(c.togglers.cssReq) // add base/required styles
          					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
          					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
          					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
          					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
          					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
          					.appendTo($R) // append SPAN to resizer DIV
          				;
          
          				// ADD INNER-SPANS TO TOGGLER
          				if (o.togglerContent_open) // ui-layout-open
          					$("<span>"+ o.togglerContent_open +"</span>")
          						.addClass("content content-open")
          						.css("display", s.isClosed ? "none" : "block")
          						.appendTo( $T )
          					;
          				if (o.togglerContent_closed) // ui-layout-closed
          					$("<span>"+ o.togglerContent_closed +"</span>")
          						.addClass("content content-closed")
          						.css("display", s.isClosed ? "block" : "none")
          						.appendTo( $T )
          					;
          
          				 // ADD BASIC VISUAL STYLES
          				if (o.applyDefaultStyles)
          					$T.css(c.togglers.cssDef);
          
          				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          			}
          
          		});
          
          		// SET ALL HANDLE SIZES & LENGTHS
          		sizeHandles("all", true); // true = onInit
          	};
          
          	/**
          	 * initResizable
          	 *
          	 * Add resize-bars to all panes that specify it in options
          	 *
          	 * @dependancies  $.fn.resizable - will abort if not found
          	 * @callers  create()
          	 */
          	var initResizable = function () {
          		var
          			draggingAvailable = (typeof $.fn.draggable == "function")
          		,	minPosition, maxPosition, edge // set in start()
          		;
          
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			;
          			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
          				o.resizable = false;
          				return true; // skip to next
          			}
          
          			var 
          				rClass				= o.resizerClass
          			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
          			,	dragClass			= rClass+"-drag"			// resizer-drag
          			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
          			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
          			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
          			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
          			,	draggingClassSet	= false 					// logic var
          			,	$P 					= $Ps[pane]
          			,	$R					= $Rs[pane]
          			;
          
          			if (!s.isClosed)
          				$R
          					.attr("title", o.resizerTip)
          					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
          				;
          
          			$R.draggable({
          				containment:	$Container[0] // limit resizing to layout container
          			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
          			,	delay:			200
          			,	distance:		1
          			//	basic format for helper - style it using class: .ui-draggable-dragging
          			,	helper:			"clone"
          			,	opacity:		o.resizerDragOpacity
          			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
          			,	zIndex:			c.zIndex.resizing
          
          			,	start: function (e, ui) {
          					// onresize_start callback - will CANCEL hide if returns false
          					// TODO: CONFIRM that dragging can be cancelled like this???
          					if (false === execUserCallback(pane, o.onresize_start)) return false;
          
          					s.isResizing = true; // prevent pane from closing while resizing
          					clearTimer(pane, "closeSlider"); // just in case already triggered
          
          					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
          					draggingClassSet = false; // reset logic var - see drag()
          
          					// SET RESIZING LIMITS - used in drag()
          					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
          					setPaneMinMaxSizes(pane); // update pane-state
          					s.minPosition -= resizerWidth;
          					s.maxPosition -= resizerWidth;
          					edge = (c[pane].dir=="horz" ? "top" : "left");
          
          					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
          					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
          						$('<div class="ui-layout-mask"/>')
          							.css({
          								background:	"#fff"
          							,	opacity:	"0.001"
          							,	zIndex:		9
          							,	position:	"absolute"
          							,	width:		this.offsetWidth+"px"
          							,	height:		this.offsetHeight+"px"
          							})
          							.css($(this).offset()) // top & left
          							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
          						;
          					});
          				}
          
          			,	drag: function (e, ui) {
          					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
          						$(".ui-draggable-dragging")
          							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
          							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
          						;
          						draggingClassSet = true;
          						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
          						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
          					}
          					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
          					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
          					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
          				}
          
          			,	stop: function (e, ui) {
          					var 
          						dragPos	= ui.position
          					,	resizerPos
          					,	newSize
          					;
          					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
          	
          					switch (pane) {
          						case "north":	resizerPos = dragPos.top; break;
          						case "west":	resizerPos = dragPos.left; break;
          						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
          						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
          					}
          					// remove container margin from resizer position to get the pane size
          					newSize = resizerPos - cDims[ c[pane].edge ];
          
          					sizePane(pane, newSize);
          
          					// UN-MASK PANES MASKED IN drag.start
          					$("div.ui-layout-mask").remove(); // Remove iframe masks	
          
          					s.isResizing = false;
          				}
          
          			});
          		});
          	};
          
          
          
          /*
           * ###########################
           *       ACTION METHODS
           * ###########################
           */
          
          	/**
          	 * hide / show
          	 *
          	 * Completely 'hides' a pane, including its spacing - as if it does not exist
          	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
          	 *
          	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
          	 */
          	var hide = function (pane, onInit) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onhide_start)) return;
          
          		s.isSliding = false; // just in case
          
          		// now hide the elements
          		if ($R) $R.hide(); // hide resizer-bar
          		if (onInit || s.isClosed) {
          			s.isClosed = true; // to trigger open-animation on show()
          			s.isHidden  = true;
          			$P.hide(); // no animation when loading page
          			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          			execUserCallback(pane, o.onhide_end || o.onhide);
          		}
          		else {
          			s.isHiding = true; // used by onclose
          			close(pane, false); // adjust all panes to fit
          			//s.isHidden  = true; - will be set by close - if not cancelled
          		}
          	};
          
          	var show = function (pane, openPane) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onshow_start)) return;
          
          		s.isSliding = false; // just in case
          		s.isShowing = true; // used by onopen/onclose
          		//s.isHidden  = false; - will be set by open/close - if not cancelled
          
          		// now show the elements
          		if ($R && o.spacing_open > 0) $R.show();
          		if (openPane === false)
          			close(pane, true); // true = force
          		else
          			open(pane); // adjust all panes to fit
          	};
          
          
          	/**
          	 * toggle
          	 *
          	 * Toggles a pane open/closed by calling either open or close
          	 *
          	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
          	 */
          	var toggle = function (pane) {
          		var s = state[pane];
          		if (s.isHidden)
          			show(pane); // will call 'open' after unhiding it
          		else if (s.isClosed)
          			open(pane);
          		else
          			close(pane);
          	};
          
          	/**
          	 * close
          	 *
          	 * Close the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being closed, ie: north, south, east, or west
          	 */
          	var close = function (pane, force, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_sliding= "-sliding"
          		,	_closed	= "-closed"
          		// 	transfer logic vars to temp vars
          		,	isShowing = s.isShowing
          		,	isHiding = s.isHiding
          		;
          		// now clear the logic vars
          		delete s.isShowing;
          		delete s.isHiding;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!force && s.isClosed && !isShowing) return; // already closed
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("close", pane, force); // set a callback for this action, if possible
          			return; // ABORT 
          		}
          
          		// onclose_start callback - will CANCEL hide if returns false
          		// SKIP if just 'showing' a hidden pane as 'closed'
          		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		s.isClosed = true;
          		// update isHidden BEFORE sizing panes
          		if (isHiding) s.isHidden = true;
          		else if (isShowing) s.isHidden = false;
          
          		// sync any 'pin buttons'
          		syncPinBtns(pane, false);
          
          		// resize panes adjacent to this one
          		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          
          		// if this pane has a resizer bar, move it now
          		if ($R) {
          			$R
          				.css(edge, cDims[edge]) // move the resizer bar
          				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
          				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
          				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
          			;
          			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
          			if (o.resizable)
          				$R
          					.draggable("disable")
          					.css("cursor", "default")
          					.attr("title","")
          				;
          			// if pane has a toggler button, adjust that too
          			if ($T) {
          				$T
          					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
          					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
          					.attr("title", o.togglerTip_closed) // may be blank
          				;
          			}
          			sizeHandles(); // resize 'length' and position togglers for adjacent panes
          		}
          
          		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
          		if (doFX) {
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
          				lockPaneForFX(pane, false); // undo
          				if (!s.isClosed) return; // pane was opened before animation finished!
          				close_2();
          			});
          		}
          		else {
          			$P.hide(); // just hide pane NOW
          			close_2();
          		}
          
          		// SUBROUTINE
          		function close_2 () {
          			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          
          			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
          			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
          			// onhide OR onshow callback
          			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
          			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          
          	/**
          	 * open
          	 *
          	 * Open the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being opened, ie: north, south, east, or west
          	 */
          	var open = function (pane, slide, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_closed	= "-closed"
          		,	_sliding= "-sliding"
          		// 	transfer logic var to temp var
          		,	isShowing = s.isShowing
          		;
          		// now clear the logic var
          		delete s.isShowing;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!s.isClosed && !s.isSliding) return; // already open
          
          		// pane can ALSO be unhidden by just calling show(), so handle this scenario
          		if (s.isHidden && !isShowing) {
          			show(pane, true);
          			return;
          		}
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
          			return; // ABORT
          		}
          
          		// onopen_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onopen_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		// 'PIN PANE' - stop sliding
          		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
          			bindStopSlidingEvents(pane, false); // will set isSliding=false
          
          		s.isClosed = false;
          		// update isHidden BEFORE sizing panes
          		if (isShowing) s.isHidden = false;
          
          		// Container size may have changed - shrink the pane if now 'too big'
          		setPaneMinMaxSizes(pane); // update pane-state
          		if (s.size > s.maxSize) // pane is too big! resize it before opening
          			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
          
          		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
          
          		if (doFX) { // ANIMATE
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
          				lockPaneForFX(pane, false); // undo
          				if (s.isClosed) return; // pane was closed before animation finished!
          				open_2(); // continue
          			});
          		}
          		else {// no animation
          			$P.show();	// just show pane and...
          			open_2();	// continue
          		}
          
          		// SUBROUTINE
          		function open_2 () {
          			// NOTE: if isSliding, then other panes are NOT 'resized'
          			if (!s.isSliding) // resize all panes adjacent to this one
          				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
          
          			// if this pane has a toggler, move it now
          			if ($R) {
          				$R
          					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
          					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
          					.addClass( rClass+_open +" "+ rClass+_pane+_open )
          					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
          				;
          				if (o.resizable)
          					$R
          						.draggable("enable")
          						.css("cursor", o.resizerCursor)
          						.attr("title", o.resizerTip)
          					;
          				else
          					$R.css("cursor", "default"); // n-resize, s-resize, etc
          				// if pane also has a toggler button, adjust that too
          				if ($T) {
          					$T
          						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
          						.addClass( tClass+_open +" "+ tClass+_pane+_open )
          						.attr("title", o.togglerTip_open) // may be blank
          					;
          				}
          				sizeHandles("all"); // resize resizer & toggler sizes for all panes
          			}
          
          			// resize content every time pane opens - to be sure
          			sizeContent(pane);
          
          			// sync any 'pin buttons'
          			syncPinBtns(pane, !s.isSliding);
          
          			// onopen callback
          			execUserCallback(pane, o.onopen_end || o.onopen);
          
          			// onshow callback
          			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          	
          
          	/**
          	 * lockPaneForFX
          	 *
          	 * Must set left/top on East/South panes so animation will work properly
          	 *
          	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
          	 * @param Boolean  doLock  true = set left/top, false = remove
          	 */
          	var lockPaneForFX = function (pane, doLock) {
          		var $P = $Ps[pane];
          		if (doLock) {
          			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
          			if (pane=="south")
          				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
          			else if (pane=="east")
          				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
          		}
          		else {
          			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
          			if (pane=="south")
          				$P.css({ top: "auto" });
          			else if (pane=="east")
          				$P.css({ left: "auto" });
          		}
          	};
          
          
          	/**
          	 * bindStartSlidingEvent
          	 *
          	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
          	 *
          	 * @callers  open(), close()
          	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
          	 * @param Boolean  enable  Enable or Disable sliding?
          	 */
          	var bindStartSlidingEvent = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	$R		= $Rs[pane]
          		,	trigger	= o.slideTrigger_open
          		;
          		if (!$R || !o.slidable) return;
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
          		$R
          			// add or remove trigger event
          			[enable ? "bind" : "unbind"](trigger, slideOpen)
          			// set the appropriate cursor & title/tip
          			.css("cursor", (enable ? o.sliderCursor: "default"))
          			.attr("title", (enable ? o.sliderTip : ""))
          		;
          	};
          
          	/**
          	 * bindStopSlidingEvents
          	 *
          	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
          	 * Also increases zIndex when pane is sliding open
          	 * See bindStartSlidingEvent for code to control 'slide open'
          	 *
          	 * @callers  slideOpen(), slideClosed()
          	 * @param String  pane  The pane to process, 'north', 'south', etc.
          	 * @param Boolean  isOpen  Is pane open or closed?
          	 */
          	var bindStopSlidingEvents = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	s		= state[pane]
          		,	trigger	= o.slideTrigger_close
          		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          
          		s.isSliding = enable; // logic
          		clearTimer(pane, "closeSlider"); // just in case
          
          		// raise z-index when sliding
          		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
          		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
          
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
          
          		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
          		if (enable) { // BIND trigger events
          			$P.bind(trigger, slideClosed );
          			$R.bind(trigger, slideClosed );
          			if (trigger = "mouseout") {
          				$P.bind("mouseover", cancelMouseOut );
          				$R.bind("mouseover", cancelMouseOut );
          			}
          		}
          		else { // UNBIND trigger events
          			// TODO: why does unbind of a 'single function' not work reliably?
          			//$P[action](trigger, slideClosed );
          			$P.unbind(trigger);
          			$R.unbind(trigger);
          			if (trigger = "mouseout") {
          				//$P[action]("mouseover", cancelMouseOut );
          				$P.unbind("mouseover");
          				$R.unbind("mouseover");
          				clearTimer(pane, "closeSlider");
          			}
          		}
          
          		// SUBROUTINE for mouseout timer clearing
          		function cancelMouseOut (evt) {
          			clearTimer(pane, "closeSlider");
          			evt.stopPropagation();
          		}
          	};
          
          	var slideOpen = function () {
          		var pane = $(this).attr("resizer"); // attr added by initHandles
          		if (state[pane].isClosed) { // skip if already open!
          			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
          			open(pane, true); // true = slide - ie, called from here!
          		}
          	};
          
          	var slideClosed = function () {
          		var
          			$E = $(this)
          		,	pane = $E.attr("pane") || $E.attr("resizer")
          		,	o = options[pane]
          		,	s = state[pane]
          		;
          		if (s.isClosed || s.isResizing)
          			return; // skip if already closed OR in process of resizing
          		else if (o.slideTrigger_close == "click")
          			close_NOW(); // close immediately onClick
          		else // trigger = mouseout - use a delay
          			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
          
          		// SUBROUTINE for timed close
          		function close_NOW () {
          			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
          			if (!s.isClosed) close(pane); // skip if already closed!
          		}
          	};
          
          
          	/**
          	 * sizePane
          	 *
          	 * @callers  initResizable.stop()
          	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
          	 * @param Integer  newSize  The new size for this pane - will be validated
          	 */
          	var sizePane = function (pane, size) {
          		// TODO: accept "auto" as size, and size-to-fit pane content
          		var 
          			edge	= c[pane].edge
          		,	dir		= c[pane].dir
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          		// calculate 'current' min/max sizes
          		setPaneMinMaxSizes(pane); // update pane-state
          		// compare/update calculated min/max to user-options
          		s.minSize = max(s.minSize, o.minSize);
          		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
          		// validate passed size
          		size = max(size, s.minSize);
          		size = min(size, s.maxSize);
          		s.size = size; // update state
          
          		// move the resizer bar and resize the pane
          		$R.css( edge, size + cDims[edge] );
          		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
          
          		// resize all the adjacent panes, and adjust their toggler buttons
          		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
          		sizeHandles();
          		sizeContent(pane);
          		execUserCallback(pane, o.onresize_end || o.onresize);
          	};
          
          	/**
          	 * sizeMidPanes
          	 *
          	 * @callers  create(), open(), close(), onWindowResize()
          	 */
          	var sizeMidPanes = function (panes, overrideDims, onInit) {
          		if (!panes || panes == "all") panes = "east,west,center";
          
          		var d = getPaneDims();
          		if (overrideDims) $.extend( d, overrideDims );
          
          		$.each(panes.split(","), function() {
          			if (!$Ps[this]) return; // NO PANE - skip
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	hasRoom	= true
          			,	CSS		= {}
          			;
          
          			if (pane == "center") {
          				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
          				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
          				CSS.width  = max(1, cssW(pane, CSS.width));
          				CSS.height = max(1, cssH(pane, CSS.height));
          				hasRoom = (CSS.width > 1 && CSS.height > 1);
          				/*
          				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
          				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
          				 */
          				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
          					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
          					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
          				}
          			}
          			else { // for east and west, set only the height
          				CSS.top = d.top;
          				CSS.bottom = d.bottom;
          				CSS.height = max(1, cssH(pane, d.height));
          				hasRoom = (CSS.height > 1);
          			}
          
          			if (hasRoom) {
          				$P.css(CSS);
          				if (s.noRoom) {
          					s.noRoom = false;
          					if (s.isHidden) return;
          					else show(pane, !s.isClosed);
          					/* OLD CODE - keep until sure line above works right!
          					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
          					if ($R) $R.show();
          					*/
          				}
          				if (!onInit) {
          					sizeContent(pane);
          					execUserCallback(pane, o.onresize_end || o.onresize);
          				}
          			}
          			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
          				s.noRoom = true; // update state
          				if (s.isHidden) return;
          				if (onInit) { // skip onhide callback and other logic onLoad
          					$P.hide();
          					if ($R) $R.hide();
          				}
          				else hide(pane);
          			}
          		});
          	};
          
          
          	var sizeContent = function (panes) {
          		if (!panes || panes == "all") panes = c.allPanes;
          
          		$.each(panes.split(","), function() {
          			if (!$Cs[this]) return; // NO CONTENT - skip
          			var 
          				pane	= str(this)
          			,	ignore	= options[pane].contentIgnoreSelector
          			,	$P		= $Ps[pane]
          			,	$C		= $Cs[pane]
          			,	e_C		= $C[0]		// DOM element
          			,	height	= cssH($P);	// init to pane.innerHeight
          			;
          			$P.children().each(function() {
          				if (this == e_C) return; // Content elem - skip
          				var $E = $(this);
          				if (!ignore || !$E.is(ignore))
          					height -= $E.outerHeight();
          			});
          			if (height > 0)
          				height = cssH($C, height);
          			if (height < 1)
          				$C.hide(); // no room for content!
          			else
          				$C.css({ height: height }).show();
          		});
          	};
          
          
          	/**
          	 * sizeHandles
          	 *
          	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
          	 *
          	 * @callers  initHandles(), open(), close(), resizeAll()
          	 */
          	var sizeHandles = function (panes, onInit) {
          		if (!panes || panes == "all") panes = c.borderPanes;
          
          		$.each(panes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	$T		= $Ts[pane]
          			;
          			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
          
          			var 
          				dir			= c[pane].dir
          			,	_state		= (s.isClosed ? "_closed" : "_open")
          			,	spacing		= o["spacing"+ _state]
          			,	togAlign	= o["togglerAlign"+ _state]
          			,	togLen		= o["togglerLength"+ _state]
          			,	paneLen
          			,	offset
          			,	CSS = {}
          			;
          			if (spacing == 0) {
          				$R.hide();
          				return;
          			}
          			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
          				$R.show(); // in case was previously hidden
          
          			// Resizer Bar is ALWAYS same width/height of pane it is attached to
          			if (dir == "horz") { // north/south
          				paneLen = $P.outerWidth();
          				$R.css({
          					width:	max(1, cssW($R, paneLen)) // account for borders & padding
          				,	height:	max(1, cssH($R, spacing)) // ditto
          				,	left:	cssNum($P, "left")
          				});
          			}
          			else { // east/west
          				paneLen = $P.outerHeight();
          				$R.css({
          					height:	max(1, cssH($R, paneLen)) // account for borders & padding
          				,	width:	max(1, cssW($R, spacing)) // ditto
          				,	top:	cDims.top + getPaneSize("north", true)
          				//,	top:	cssNum($Ps["center"], "top")
          				});
          				
          			}
          
          			if ($T) {
          				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
          					$T.hide(); // always HIDE the toggler when 'sliding'
          					return;
          				}
          				else
          					$T.show(); // in case was previously hidden
          
          				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
          					togLen = paneLen;
          					offset = 0;
          				}
          				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
          					if (typeof togAlign == "string") {
          						switch (togAlign) {
          							case "top":
          							case "left":	offset = 0;
          											break;
          							case "bottom":
          							case "right":	offset = paneLen - togLen;
          											break;
          							case "middle":
          							case "center":
          							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
          						}
          					}
          					else { // togAlign = number
          						var x = parseInt(togAlign); //
          						if (togAlign >= 0) offset = x;
          						else offset = paneLen - togLen + x; // NOTE: x is negative!
          					}
          				}
          
          				var
          					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
          				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
          				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
          				;
          				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
          				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
          
          				if (dir == "horz") { // north/south
          					var width = cssW($T, togLen);
          					$T.css({
          						width:	max(0, width)  // account for borders & padding
          					,	height:	max(1, cssH($T, spacing)) // ditto
          					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
          				}
          				else { // east/west
          					var height = cssH($T, togLen);
          					$T.css({
          						height:	max(0, height)  // account for borders & padding
          					,	width:	max(1, cssW($T, spacing)) // ditto
          					,	top:	offset // POSITION the toggler
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
          				}
          
          
          			}
          
          			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
          			if (onInit && o.initHidden) {
          				$R.hide();
          				if ($T) $T.hide();
          			}
          		});
          	};
          
          
          	/**
          	 * resizeAll
          	 *
          	 * @callers  window.onresize(), callbacks or custom code
          	 */
          	var resizeAll = function () {
          		var
          			oldW	= cDims.innerWidth
          		,	oldH	= cDims.innerHeight
          		;
          		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
          
          		var
          			checkH	= (cDims.innerHeight < oldH)
          		,	checkW	= (cDims.innerWidth < oldW)
          		,	s, dir
          		;
          
          		if (checkH || checkW)
          			// NOTE special order for sizing: S-N-E-W
          			$.each(["south","north","east","west"], function(i,pane) {
          				s = state[pane];
          				dir = c[pane].dir;
          				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
          					setPaneMinMaxSizes(pane); // update pane-state
          					// shrink pane if 'too big' to fit
          					if (s.size > s.maxSize)
          						sizePane(pane, s.maxSize);
          				}
          			});
          
          		sizeMidPanes("all");
          		sizeHandles("all"); // reposition the toggler elements
          	};
          
          
          	/**
          	 * keyDown
          	 *
          	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
          	 *
          	 * @callers  document.keydown()
          	 */
          	function keyDown (evt) {
          		if (!evt) return true;
          		var code = evt.keyCode;
          		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
          
          		var
          			PANE = {
          				38: "north" // Up Cursor
          			,	40: "south" // Down Cursor
          			,	37: "west"  // Left Cursor
          			,	39: "east"  // Right Cursor
          			}
          		,	isCursorKey = (code >= 37 && code <= 40)
          		,	ALT = evt.altKey // no worky!
          		,	SHIFT = evt.shiftKey
          		,	CTRL = evt.ctrlKey
          		,	pane = false
          		,	s, o, k, m, el
          		;
          
          		if (!CTRL && !SHIFT)
          			return true; // no modifier key - abort
          		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
          			pane = PANE[code];
          		else // check to see if this matches a custom-hotkey
          			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
          				o = options[p];
          				k = o.customHotkey;
          				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
          				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
          					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
          						pane = p;
          						return false; // BREAK
          					}
          				}
          			});
          
          		if (!pane) return true; // no hotkey - abort
          
          		// validate pane
          		o = options[pane]; // get pane options
          		s = state[pane]; // get pane options
          		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
          
          		// see if user is in a 'form field' because may be 'selecting text'!
          		el = evt.target || evt.srcElement;
          		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
          			return true; // allow text-selection
          
          		// SYNTAX NOTES
          		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
          		// use "return false" to abort keystroke AND abort function
          		toggle(pane);
          		evt.stopPropagation();
          		evt.returnValue = false; // CANCEL key
          		return false;
          	};
          
          
          /*
           * ###########################
           *     UTILITY METHODS
           *   called externally only
           * ###########################
           */
          
          	function allowOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).attr("pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		;
          
          		// if pane is already raised, then reset it before doing it again!
          		// this would happen if allowOverflow is attached to BOTH the pane and an element 
          		if (s.cssSaved)
          			resetOverflow(pane); // reset previous CSS before continuing
          
          		// if pane is raised by sliding or resizing, or it's closed, then abort
          		if (s.isSliding || s.isResizing || s.isClosed) {
          			s.cssSaved = false;
          			return;
          		}
          
          		var
          			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
          		,	curCSS	= {}
          		,	of		= $P.css("overflow")
          		,	ofX		= $P.css("overflowX")
          		,	ofY		= $P.css("overflowY")
          		;
          		// determine which, if any, overflow settings need to be changed
          		if (of != "visible") {
          			curCSS.overflow = of;
          			newCSS.overflow = "visible";
          		}
          		if (ofX && ofX != "visible" && ofX != "auto") {
          			curCSS.overflowX = ofX;
          			newCSS.overflowX = "visible";
          		}
          		if (ofY && ofY != "visible" && ofY != "auto") {
          			curCSS.overflowY = ofX;
          			newCSS.overflowY = "visible";
          		}
          
          		// save the current overflow settings - even if blank!
          		s.cssSaved = curCSS;
          
          		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
          		$P.css( newCSS );
          
          		// make sure the zIndex of all other panes is normal
          		$.each(c.allPanes.split(","), function(i, p) {
          			if (p != pane) resetOverflow(p);
          		});
          
          	};
          
          	function resetOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		,	CSS		= s.cssSaved || {}
          		;
          		// reset the zIndex
          		if (!s.isSliding && !s.isResizing)
          			$P.css("zIndex", c.zIndex.pane_normal);
          
          		// reset Overflow - if necessary
          		$P.css( CSS );
          
          		// clear var
          		s.cssSaved = false;
          	};
          
          
          	/**
          	* getBtn
          	*
          	* Helper function to validate params received by addButton utilities
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
          	*/
          	function getBtn(selector, pane, action) {
          		var
          			$E = $(selector)
          		,	err = "Error Adding Button \n\nInvalid "
          		;
          		if (!$E.length) // element not found
          			alert(err+"selector: "+ selector);
          		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
          			alert(err+"pane: "+ pane);
          		else { // VALID
          			var btn = options[pane].buttonClass +"-"+ action;
          			$E.addClass( btn +" "+ btn +"-"+ pane );
          			return $E;
          		}
          		return false;  // INVALID
          	};
          
          
          	/**
          	* addToggleBtn
          	*
          	* Add a custom Toggler button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addToggleBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "toggle");
          		if ($E)
          			$E
          				.attr("title", state[pane].isClosed ? "Open" : "Close")
          				.click(function (evt) {
          					toggle(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addOpenBtn
          	*
          	* Add a custom Open button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addOpenBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "open");
          		if ($E)
          			$E
          				.attr("title", "Open")
          				.click(function (evt) {
          					open(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addCloseBtn
          	*
          	* Add a custom Close button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addCloseBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "close");
          		if ($E)
          			$E
          				.attr("title", "Close")
          				.click(function (evt) {
          					close(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addPinBtn
          	*
          	* Add a custom Pin button for a pane
          	*
          	* Four classes are added to the element, based on the paneClass for the associated pane...
          	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
          	*  - ui-layout-pane-pin
          	*  - ui-layout-pane-west-pin
          	*  - ui-layout-pane-pin-up
          	*  - ui-layout-pane-west-pin-up
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
          	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
          	*/
          	function addPinBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "pin");
          		if ($E) {
          			var s = state[pane];
          			$E.click(function (evt) {
          				setPinState($(this), pane, (s.isSliding || s.isClosed));
          				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
          				else close( pane ); // slide-closed
          				evt.stopPropagation();
          			});
          			// add up/down pin attributes and classes
          			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
          			// add this pin to the pane data so we can 'sync it' automatically
          			// PANE.pins key is an array so we can store multiple pins for each pane
          			c[pane].pins.push( selector ); // just save the selector string
          		}
          	};
          
          	/**
          	* syncPinBtns
          	*
          	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
          	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
          	*
          	* @callers  open(), close()
          	* @params  pane   These are the params returned to callbacks by layout()
          	* @params  doPin  True means set the pin 'down', False means 'up'
          	*/
          	function syncPinBtns (pane, doPin) {
          		$.each(c[pane].pins, function (i, selector) {
          			setPinState($(selector), pane, doPin);
          		});
          	};
          
          	/**
          	* setPinState
          	*
          	* Change the class of the pin button to make it look 'up' or 'down'
          	*
          	* @callers  addPinBtn(), syncPinBtns()
          	* @param Element  $Pin		The pin-span element in a jQuery wrapper
          	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
          	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
          	*/
          	function setPinState ($Pin, pane, doPin) {
          		var updown = $Pin.attr("pin");
          		if (updown && doPin == (updown=="down")) return; // already in correct state
          		var
          			root	= options[pane].buttonClass
          		,	class1	= root +"-pin"
          		,	class2	= class1 +"-"+ pane
          		,	UP1		= class1 + "-up"
          		,	UP2		= class2 + "-up"
          		,	DN1		= class1 + "-down"
          		,	DN2		= class2 + "-down"
          		;
          		$Pin
          			.attr("pin", doPin ? "down" : "up") // logic
          			.attr("title", doPin ? "Un-Pin" : "Pin")
          			.removeClass( doPin ? UP1 : DN1 ) 
          			.removeClass( doPin ? UP2 : DN2 ) 
          			.addClass( doPin ? DN1 : UP1 ) 
          			.addClass( doPin ? DN2 : UP2 ) 
          		;
          	};
          
          
          /*
           * ###########################
           * CREATE/RETURN BORDER-LAYOUT
           * ###########################
           */
          
          	// init global vars
          	var 
          		$Container = $(this).css({ overflow: "hidden" }) // Container elem
          	,	$Ps		= {} // Panes x4	- set in initPanes()
          	,	$Cs		= {} // Content x4	- set in initPanes()
          	,	$Rs		= {} // Resizers x4	- set in initHandles()
          	,	$Ts		= {} // Togglers x4	- set in initHandles()
          	//	object aliases
          	,	c		= config // alias for config hash
          	,	cDims	= state.container // alias for easy access to 'container dimensions'
          	;
          
          	// create the border layout NOW
          	create();
          
          	// return object pointers to expose data & option Properties, and primary action Methods
          	return {
          		options:		options			// property - options hash
          	,	state:			state			// property - dimensions hash
          	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
          	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
          	,	open:			open			// method - ditto
          	,	close:			close			// method - ditto
          	,	hide:			hide			// method - ditto
          	,	show:			show			// method - ditto
          	,	resizeContent:	sizeContent		// method - ditto
          	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
          	,	resizeAll:		resizeAll		// method - no parameters
          	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
          	,	addOpenBtn:		addOpenBtn		// utility - ditto
          	,	addCloseBtn:	addCloseBtn		// utility - ditto
          	,	addPinBtn:		addPinBtn		// utility - ditto
          	,	allowOverflow:	allowOverflow	// utility - pass calling element
          	,	resetOverflow:	resetOverflow	// utility - ditto
          	,	cssWidth:		cssW
          	,	cssHeight:		cssH
          	};
          
          }
          })( jQuery );
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        22. GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (369 bytes)
          GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 25809
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"25809-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (25809 bytes)
          /**
           * Version: 1.0 Alpha-1 
           * Build Date: 13-Nov-2007
           * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
           * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
           * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
           */
          Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
          Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
          return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
          if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
          var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
          if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
          if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
          if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
          if(x.month||x.months){this.addMonths(x.month||x.months);}
          if(x.year||x.years){this.addYears(x.year||x.years);}
          if(x.day||x.days){this.addDays(x.day||x.days);}
          return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
          return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
          if(!x.second&&x.second!==0){x.second=-1;}
          if(!x.minute&&x.minute!==0){x.minute=-1;}
          if(!x.hour&&x.hour!==0){x.hour=-1;}
          if(!x.day&&x.day!==0){x.day=-1;}
          if(!x.month&&x.month!==0){x.month=-1;}
          if(!x.year&&x.year!==0){x.year=-1;}
          if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
          if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
          if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
          if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
          if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
          if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
          if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
          if(x.timezone){this.setTimezone(x.timezone);}
          if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
          return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
          var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
          return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
          Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
          return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
          var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
          return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
          var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
          return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
          (function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
          break;}
          return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
          return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
          throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
          return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
          if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){r=null;}
          if(r){return r;}}
          throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
          return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
          rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
          s=q[1];}
          if(!r){throw new $P.Exception(s);}
          if(q){throw new $P.Exception(q[1]);}
          if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
          return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
          rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
          if(!last&&q[1].length===0){last=true;}
          if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
          p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
          if(rx[1].length<best[1].length){best=rx;}
          if(best[1].length===0){break;}}
          if(best[0].length===0){return best;}
          if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
          best[1]=q[1];}
          return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
          return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
          if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
          var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
          return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
          this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
          var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
          return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
          for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
          if(this.now){return new Date();}
          var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
          if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
          if(!this.unit){this.unit="day";}
          if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
          if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
          this[this.unit+"s"]=this.value*orient;}
          return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
          if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
          if(this.month&&!this.day){this.day=1;}
          return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
          fn=_C[keys]=_.any.apply(null,px);}
          return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
          return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
          return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
          try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        23. GET https://dev.duracloud.org/duradmin/style/base.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (362 bytes)
          GET https://dev.duracloud.org/duradmin/style/base.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (437 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 21115
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"21115-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (21115 bytes)
          /*
          * Created by Daniel Bernstein
          * Modified by Charles Hacskaylo
          */
          
          /* RESETTERS *************************************************/
          /* Eric Meyer:
          /* v1.0 | 20080212 */
          
          html, body, div, span, applet, object, iframe,
          h1, h2, h3, h4, h5, h6, p, blockquote, pre,
          a, abbr, acronym, address, big, button, cite, code,
          del, dfn, em, font, img, ins, kbd, q, s, samp,
          small, strike, strong, sub, sup, tt, var,
          b, u, i, center,
          dl, dt, dd, ol, ul, li,
          fieldset, form, label, legend,
          table, caption, tbody, tfoot, thead, tr, th, td {
          	margin: 0;
          	padding: 0;
          	border: 0;
          	outline: 0;
          	font-size: 100%;
          	vertical-align: baseline;
          	background: transparent;
          }
          body {
          	line-height: 1;
          }
          
          a:hover {
            cursor:pointer;
          }
          
          ol, ul {
          	list-style: none;
          }
          
          
          ul.bullets,
          #static-panel ul
          {
          	line-height:130%;
          	list-style:square;
          	margin-left:15px;
          }
          
          blockquote, q {
          	quotes: none;
          }
          blockquote:before, blockquote:after,
          q:before, q:after {
          	content: '';
          	content: none;
          }
          
          /* remember to define focus styles! */
          :focus {
          	outline: 0;
          }
          
          /* tables still need 'cellspacing="0"' in the markup */
          table {
          	border-collapse: collapse;
          	border-spacing: 0;
          }
          
          /* set input color for autofill */
          input:-webkit-autofill {
              color: #000 !important;
          }
          
          
          
          
          
          
          /* CLEARFIX *************************************************/
          
          .clearfix:after {
               visibility: hidden;
               display: block;
               font-size: 0;
               content: " ";
               clear: both;
               height: 0;
               }
          .clearfix { display: inline-block; }
          /* start commented backslash hack \*/
          * html .clearfix { height: 1%; }
          .clearfix { display: block; }
          /* close commented backslash hack */
          
          
          .horizontal-list li
          {
          	display:inline-block;
          }
          
          
          body {
          	background:#fff url(../images/bg_clouds.jpg) repeat-y;
          	font-family: Verdana, Helvetica, sans-serif;
          	font-size:1em;
          	*font-size:	90%; /* IE only */
          	margin-right:10px !important;
          }
          
          h1, h2, h3
          {
          	font-family:Helvetica, Sans-Serif;
          }
          
          h1 { font-size:2em; font-weight:normal; }
          h2 { font-size:1.3em; font-weight:normal; }
          h3 { font-size:1em; }
          
          
          .float-l {float:left; margin-left:0; }
          .float-r {float:right; margin-right:0; }
          .content-centered { text-align:center !important; }
          
          
          /* MAIN PAGE ELEMENTS ******************************************/
          
          body > #page-header
          {
          	height:87px;
          	min-width:960px;
          	padding-top:10px;
          }
          
          .pane-L1-body
          {
          	background:url(../images/bg_L1.png) no-repeat top right;
          	padding-top:5px;
          }
          
          .pane-L1-body a
          {
          	color:#ccc;
          }
          
          .center-pane-north
          {
          	color:#9b9b9b;
          	font-size:13px;
          	padding:5px 10px;
          	z-index:4 !important; /* needed to list spaces provider menu above elements below it */
          }
          
          .dc-prototype {
          
          	display:none;
          }
          
          .list-browser
          {
          	background:#4F4F4F no-repeat top right;
          }
          
          .ui-layout-pane-west
          {
          	font-size:11px;
          }
          
          .dc-item-list-filter
          {
          	background-color:#4F4F4F;
          	border:1px solid #999;
          	color:#ccc;
          	font-style:italic;
          	padding:2px;
          	width:143px;
          	float: right;
          }
          
          .dc-item-list-wrapper
          {
          	background-color:#cbcbcb;
          	border:1px solid #595959;
          	border-top-color:#333;
          	border-bottom-color:#4F4F4F;
          	color:#000;
          	min-width:250px !important;
          	overflow:auto;
          	width:auto !important;
          }
          
          .dc-item-list-wrapper a
          {
          	color:#000;
          }
          
          .dc-selectablelist-footer {
          	padding-right:10px;
          }
          
          .dc-link:hover {
          	text-decoration:underline;
          	cursor: pointer;
          }
          
          .dc-link:after {
          	content:'>';
          }
          
          .dc-selectablelist-hl {
          	background:#DDDDDD;
          }
          
          
          .list-header
          {
          	padding:5px 5px 5px 10px;
          }
          
          .header-section
          {
          	min-width:250px !important;
          	padding-bottom:3px;
          	white-space:nowrap;
          }
          
          .list-header h2
          {
          	display:inline-block;
          	font-size:16px;
          	line-height:24px;
          }
          
          #spaces-list-view .list-header .button span,
          #content-item-list-view .list-header .button span
          {
          	width:130px;
          }
          
          #space-filter {
              width: 100px;
          }
          
          .item-scroll-action:hover {
          	color:#EEE;
          	font-weight:bold;
          }
          
          .item-scroll-action{
          	text-decoration: none;
          }
          
          .ui-layout-pane
          {
          	color:#fff;
          }
          
          #provider-logo
          {
              float:left;
              margin-left:0;
              height:39px;
          	width:184px;
          }
          
          .amazon_s3-logo
          {
              background:url(../images/amazon.png) no-repeat;
          }
          
          .amazon_glacier-logo
          {
              background:url(../images/amazon.png) no-repeat;
          }
          
          .chronopolis-logo
          {
          	background:url(../images/chronopolis.png) no-repeat;
          }
          
          .swift_s3-logo
          {
              background:url(../images/swift.png) no-repeat;
          }
          
          .ui-layout-resizer
          {
          	background-color:#4b4b4b;
          	cursor:col-resize !important;
          }
          
          .ui-layout-resizer:hover
          {
          	background-color:#257bba !important;
          	cursor:col-resize !important;
          	opacity:1 !important;
          }
          
          #spaces-list-view-resizer
          {
          	background-color:#4F4F4F;
          }
          
          #list-browser-resizer
          {
          
          }
          
          ul.dc-user-config > li:first-child, .dc-exclusion-group > ul > li {
          	border-top:0px;
          }
          
          ul.dc-user-config > li:last-child {
          	border-bottom: 0px;
          }
          
          
          .dc-exclusion-group  li {
          	margin-left: 30px;
          	border-bottom: 0px;
          	border-top: 0px;
          }
          
          .dc-exclusion-group  ul {
          	margin-left:30px;
          	border-left:1px solid #555555;
          	background: #666666 !important;
          	padding-left:10px;
          }
          
          .dc-exclusion-group > ul > li > label {
          	width:250px !important;
          	margin-right:10px;
          }
          
          .dc-exclusion-group > ul > li {
          	border-bottom: 1px solid #777777;
          }
          
          .dc-exclusion-group > label, .dc-exclusion-group > select
          {
          	margin-bottom: 10px;
          }
          
          .dc-exclusion-group  li:last-child {
          	border-bottom: 0px;
          }
          
          
          .ui-layout-toggler
          {
          	background:url(../images/grippy.gif) no-repeat left top;
          	height:100px !important;
          }
          
          .footer
          {
          	background:url(../images/bg_L1_btm.png) no-repeat right -8px;
          	height:70px !important;
          	padding:0px 10px;
          }
          
          .footer #status-holder
          {
          	color:#ccc;
          	font-size:11px;
          	height:27px;
          	padding-top:2px;
          	text-align:right;
          }
          
          .footer #status-holder a { color:#ccc; text-decoration:none; }
          .footer #status-holder a:hover { color:#fff; }
          
          #status-holder #progress-bar
          {
          	background:url("/duradmin/images/loading-bar-green.gif") no-repeat left 2px;
          	display:inline-block;
          	height:20px;
          	width:110px;
          	vertical-align:middle;
          
          }
          
          #status-holder {
          }
          
          #footer-content { margin-top:15px; }
          
          #footer-content #logo-ds
          {
          	background:url(../images/logo_lyrasis.png) no-repeat top left;
          	margin-top:-5px;
          	width:116px;
          	height:18px;
          }
          
          .footer .sep
          {
          	color:#272727;
          }
          
          .hint
          {
          	font-size:11px;
          }
          
          /* TABS **********************************************/
          /* Extends css.flex *****/
          
          .dc-main-tabs
          {
          	position:absolute;
          	left:10px;
          	top:65px;
          	opacity:0.7;
          }
          
          .dc-main-tabs li
          {
          	margin:0;
          }
          
          .dc-main-tabs a,
          .dc-main-tabs a span
          {
          	color:#000;
          	font-size:13px;
          	height:22px;
          	line-height:22px;
          }
          
          .dc-main-tabs a span
          {
          	margin:0 -2px;
          	padding-left:2px;
          	font-weight:bold;
          }
          
          .dc-main-tabs .selected a,
          .dc-main-tabs a:hover
          {
          	background:url(../images/tab.gif) no-repeat top left;
          }
          
          .dc-main-tabs .selected a span,
          .dc-main-tabs a:hover span
          {
          	background:url(../images/tab.gif) no-repeat top right;
          	color:#fff !important;
          }
          
          /* LIST AND ITEMS **********************************************/
          
          .dc-item-list
          {
          	margin:5px;
          }
          
          .dc-item-list table
          {
          	width:100%;
          }
          
          .dc-item,
          .dc-item td,
          .dc-item-list th
          {
          	border-bottom:1px solid #bbbbbb;
          	border-collapse:  collapse;
          	color:#000;
          	padding-bottom:2px;
          	padding-top:2px;
          	text-align:left;
          	vertical-align:middle;
          }
          
          .dc-item {
              position:relative;
          	min-height:20px;
          }
          .dc-item-list td,
          .dc-item-list th
          {
          	padding:3px 5px;
          }
          
          .dc-item-list td.icon
          {
          	width:38px;
          }
          
          .dc-item-list th
          {
          	background-color:#aaa;
          	border-left:1px solid #ccc;
          }
          
          .dc-item-list td.icon div
          {
          	/* graphics format: art is 32 x 32, horizontal, with 10px between each, so total offset from icon to icon is 42px */
          	background:url(../images/icons_services.png) no-repeat;
          	width:32px;
          	height:32px;
          }
          
          /* replicate 0; general-compute -42; bit-integrity -84; image -126; video -168; file-transform -210; */
          
          .dc-item-list .service-replicate td.icon div { background-position:0 0; }
          .dc-item-list .service-generalcompute td.icon div { background-position:-42px 0; }
          .dc-item-list .service-bitintegrity td.icon div { background-position:-84px 0; }
          .dc-item-list .service-image td.icon div { background-position:-126px 0; }
          .dc-item-list .service-video td.icon div { background-position:-168px 0; }
          .dc-item-list .service-filetransform td.icon div { background-position:-210px 0; }
          
          /* bitintegrity */
          .dc-item-list .service-0 td.icon div { background-position:-84px 0; }
          .dc-item-list .service-1 td.icon div { background-position:-84px 0; }
          .dc-item-list .service-2 td.icon div { background-position:-84px 0; }
          
          /* image */
          .dc-item-list .service-5 td.icon div { background-position:-126px 0; }
          .dc-item-list .service-6 td.icon div { background-position:-126px 0; }
          .dc-item-list .service-7 td.icon div { background-position:-126px 0; }
          
          /* filetransform */
          .dc-item-list .service-8 td.icon div { background-position:-210px 0; }
          
          .dc-selected-list-item {
          	background-color:#7e7e7e;
          }
          
          input.dc-check-all
          {
          	margin-left:3px !important;
          }
          
          .dc-checked-selected-list-item {
          	background-color:#888;
          	color:#FFF;
          }
          
          .dc-checked-list-item {
          	background-color:#999;
          	color:#FFF;
          }
          
          .dc-item div:first-child {
          	/*
          
          	float:left;*/
          }
          
          .dc-item-list .dc-action-panel{
              position:absolute;
              right:0;
              top:4px;
          }
          
          .dc-action-panel
          {
          	/*margin-right:20px;*/
          }
          
          .dc-item-content {
              padding-right: 30px;
          }
          
          .dc-item .cb-holder{
          	padding:8px 8px 8px 5px;
          }
          
          .dc-item:hover,
          .dc-item:hover td
          {
          	background-color:#9b9b9b;
          	cursor: pointer;
          }
          
          /* PAGE TOP ********************************************************/
          
          #dc-logo-panel
          {
          	padding-left:10px;
          }
          
          #dc-logo,
          #dc-app-title
          {
          	background-repeat:no-repeat;
          	display:inline-block;
          	float:left;
          	height:45px;
          }
          
          #dc-logo
          {
          	background-image:url(../images/logo_top_duracloud.png);
          	width:110px;
          	color: transparent;
          }
          
          #page-header #dc-app-title
          {
          	width:280px;
          }
          
          #page-header #dc-user
          {
          	border-right:solid 1px #ccc;
          	height:60px;
          	margin-right:10px;
          	padding-right:20px;
          	text-align:right;
          	width:400px;
          }
          
          .outer,
          .outer a
          {
          	color:#2c2c2c;
          	font-size:14px;
          }
          
          .outer .icon-link:hover
          {
          	color:#000;
          }
          
          
          .dc-mouse-panel {
          	visibility: hidden;
          }
          
          .dc-mouse-panel-activator
          {
          	cursor:pointer;
          }
          
          .dc-toggler {
          	float:right;
          	background: url(../images/icon_sm_arw_blue_updown.gif) no-repeat right top;
          	width:11px;
          	height:25px;
          }
          
          .dc-toggler-close { background-position:left top; }
          
          
          .dc-expandable-panel div:first-child{
          	cursor: pointer;
          }
          
          /* DETAIL PANE ****************************************************/
          
          .detail-pane
          {
          	padding-right:5px !important;
          }
          
          .detail-pane h1
          {
          	color:#777;
          	margin-bottom:10px;
          }
          
          .detail-pane > .north {
          	overflow: auto;
          	overflow-x: auto;
          }
          
          .detail-pane th {
          	text-align: left;
          	background-color: #555;
          	padding: 5px 0px 5px 0px;
          }
          
          h2,.footer-prompt
          {
              color:#F0F0F0;
          }
          
          .footer-prompt {
            font-size: smaller;
          }
          
          .detail-pane h3
          {
          	color:#fff;
          	margin-bottom:10px;
          }
          
          .detail-pane .north
          {
          	background:url(../images/bg_details_header.png) repeat-x bottom left;
          	padding:0 10px;
          	position:relative;
          }
          
          .detail-pane .center
          {
          	background-color:#414141;
          	border:1px solid #2d2d2d;
          	border-top-color:#333;
          	border-bottom-color:#999;
          	font-family:Verdana, Sans-Serif;
          	font-size:11px;
          	overflow-x:hidden;
          	overflow-y:scroll;
          }
          
          .detail-pane .center {
          	width:auto !important;
          }
          
          .detail-pane .segment-header,
          #add-remove-properties-dialog .segment-header
          {
          	background:url(../images/bg_segment_header.gif) repeat-x top left;
          	border-bottom:1px solid #333;
          	color:#DBDBDB;
          	cursor:pointer;
          	font-size:13px;
          	height:28px;
          	line-height:25px;
          	padding:0 10px;
          }
          
          .detail-pane .segment-header:hover,
          #add-remove-properties-dialog .segment-header:hover
          {
          	color:#fff;
          }
          
          .detail-pane .segment-content,
          #add-remove-properties-dialog .segment-content
          {
          	padding:10px;
          }
          
          .detail-pane .segment-content table,
          #add-remove-properties-dialog .segment-content table
          {
          	width:100%;
          }
          
          .detail-pane .segment-content table td,
          #add-remove-properties-dialog .segment-content table td
          {
          	border-bottom:1px solid #555;
          	padding:4px 5px 4px 0;
          }
          
          .detail-pane .segment-content table td.label,
          span.label,
          #add-remove-properties-dialog .segment-content table td.label
          {
          	color:#999;
          }
          
          .detail-pane .segment-content table td.label,
          #add-remove-properties-dialog .segment-content table td.label
          {
          	width:30%;
          }
          
          
          .detail-pane .segment-content table td.value,
          #add-remove-properties-dialog .segment-content table td.value
          {
          	width:70%;
          }
          
          .detail-pane .segment-content input,
          #add-remove-properties-dialog .segment-content input
          {
          	background-color:#484747;
          	border:1px solid #727576;
          	color:#ccc;
          	padding:2px;
          }
          
          .segment-content h4 {
          	margin: 10px 0px 5px 0px;
          	padding: 10px 5px 10px 5px;
          	height: 25px;
          	border-top: 1px solid #555;
          }
          
          .segment-content h4 span {
          	margin-top: 5px;
          }
          .segment-content h4 button {
          	float:right;
          }
          
          
          .detail-pane .mime-type
          {
          	font-size:13px;
          	height:40px;
          	line-height:40px;
          	margin:10px 0;
          }
          
          .mime-type-image-holder
          {
          	background:url(../images/icons_mimetypes.png) no-repeat;
          	background-position:-40px 0;
          	height:40px;
          	width:40px;
          }
          
          .detail-pane .mime-type-image-holder
          {
          	margin-right:10px;
          }
          
          .mime-type-application { background-position:-80px 0 !important; }
          .mime-type-audio { background-position:-240px 0 !important; }
          .mime-type-compression { background-position:-480px 0 !important; }
          .mime-type-drawing { background-position:-200px 0 !important; }
          .mime-type-generic { background-position:0 0 !important; }
          .mime-type-globe { background-position:-160px 0 !important; }
          .mime-type-image { background-position:-200px 0 !important; }
          .mime-type-message { background-position:-280px 0 !important; }
          .mime-type-text { background-position:-320px 0 !important; }
          .mime-type-music { background-position:-360px 0 !important; }
          .mime-type-spreadsheet { background-position:-440px 0 !important; }
          .mime-type-unknown { background-position:-40px 0 !important; }
          .mime-type-xml { background-position:-520px 0 !important; }
          .mime-type-video { background-position:-120px 0 !important; }
          
          .preview-image-wrapper
          {
          	display:block;
          	margin:0 auto;
          	overflow:hidden;
          	text-align:center;
          	padding-top:10px;
          	padding-bottom:10px;
          	min-width:300px;
          	min-height:200px;
          }
          
          
          
           /* ERRORS *********************************************************/
          
           .error, .warning
           {
           	color:#ccc;
           	margin-bottom:10px;
           }
          
          .error,.failure
           {
           	border:1px solid #aa0000;
           	background-color:#990000;
           }
          .warning
           {
           	border:1px solid #ff9933;
          	background-color:#ff6600;
           }
          
           .success {
           	border:1px solid #00AA00;
          	background-color:#009900;
           }
          
           .info {
              background-color:#2e9acc;
           }
           .info, .success, .warning, .error {
          	border-radius: 5px;
          	padding:5px;
           }
          
          .detail-pane label.error {
          	padding:0px;
           }
          
           .health-check {
           	padding:5px;
           }
          
           /* MISC **********************************************************/
          
           .object-id {
           	display:none;
           }
          
           /*flyout select default styling ******************************************/
          
          .provider-widget
          {
          	display:inline-block;
          	position:relative;
          }
          
          .provider-widget ul
          {
          	-moz-border-radius:3px;
          	border-radius:3px;
          	-webkit-border-radius:3px;
          	background-color:#2886c0;
          	border:1px solid #257ab9;
          	border-bottom-color:#0c293f;
          	border-top-color:#2e9acc;
          	display:none;
          	padding:10px;
          	opacity:0.95;
          	position:absolute;
          	z-index:5000;
          }
          
          .provider-widget li
          {
          	border-top:1px solid #2e9acc;
          	white-space:nowrap;
          	min-width:100px;
          }
          
          .provider-widget li a
          {
          	color:#ffffff;
          	cursor:pointer;
          	display:block;
          	font-size:11px;
          	padding:6px 3px;
          	text-decoration:none;
          }
          
          .provider-widget li a:hover
          {
          	background-color:#2e9acc;
          	color:#fff;
          }
          
          /* doing this via jquery to support IE, so turned off here
          #select-provider-wrapper:hover ul
          {
          	display:block;
          }
          */
          
           .provider-widget li:first-child{
           	border-top:none !important;
           }
          
          .provider-widget > a,
          .provider-widget > a span
          {
          	background-image:url(../images/btn_provider.gif);
          
          }
          
          .provider-widget > a span i
          {
          	color:#76e8ff !important;
          	min-width:150px;
          }
          
          .provider-float
          {
              float: right;
          }
          
          .dc-expando-status {
          	height:20px;
          	width:30px;
          }
          
          .dc-busy {
          	background: url('../images/wait.gif') no-repeat center center;
          	display:inline-block; vertical-align:middle;
          	height:20px;
          	width:20px;
          }
          
          .dc-removing {
          	background-color: orange;
          	filter:alpha(opacity=0.25);
          	-moz-opacity:0.25;
          	-khtml-opacity: 0.25;
          	opacity: 0.25;
          }
          
          .dc-progressbar
          {
          	display:block;
          	background-color:#003300;
          	border:1px solid #000;
          	border-bottom-color:#454545;
          }
          
          .dc-progressbar .dc-progressbar-value
          {
          	background-color:#227722;
          	border:1px solid #228822;
          	border-top-color:#339933;
          	border-bottom-width:0;
          	color:#00cc00;
          	display:block;
          	overflow:visible;
          	padding:1px 0px 3px 0px;
          	text-align:left;
          	white-space:nowrap;
          }
          
          .dc-failure, .dc-progressbar .dc-failure {
          	background-color:#772222;
          	border:1px solid #882222;
          	border-top-color:#993333;
          	color:#cc0000;
          }
          
          .dc-cancelled, .dc-progress-bar .dc-cancelled {
          	background-color:#222277;
          	border:1px solid #222288;
          	border-top-color:#333399;
          	color:#0000cc;
          }
          
          
          .dc-progress-state {
          	padding-right:1em;
          }
          
          .dc-controls
          {
          	float:right;
          	color: white;
          }
          
          
          #busy-dialog-title {
          	margin-bottom:20px;
          }
          #busy-dialog-progressbar  {
          	height: 30px;
          	width: 100%;
          	background: url('../images/loading-bar-green.gif') no-repeat center center;
          }
          
          .ui-serviceconfig > div {
          	height: 420px;
          	overflow: auto;
          }
          
          
          p.ui-serviceconfig-no-config{
          	padding: 10px 0px 10px 0px;
          }
          
          /*
          * hiding the jquery-ui dialog title bars globally.
          */
          .ui-dialog-titlebar{
          	display:none;
          }
          
          
          .dc-graph {
          	width:300px;
          	height:150px;
          	padding:20px;
              margin-bottom:10px;
          }
          
          .dc-breadcrumb  li:after {
          	content:' :: '
          }
          
          
          .dc-breadcrumb li {
          	cursor: pointer;
          	font-size:0.9em;
          	color:#555
          }
          
          
          .dc-breadcrumb-title {
          	font-size:1.3em !important;
          	color:#555 !important;
          
          }
          
          
          .dc-breadcrumb ul{
          
          }
          
          .dc-report-panel {
          
          }
          
          .dc-hidden {
          	display:none;
          }
          .dc-date-slider > div {
          	 display:inline-block;
          }
          
          .number {
          	text-align:right;
          }
          
          
          
          
          table.tablesorter {
              background-color: #CDCDCD;
              font-family: arial;
              font-size: 8pt;
              margin: 10px 0 15px;
              text-align: left;
              width: 100%;
          }
          table.tablesorter thead tr th, table.tablesorter tfoot tr th {
              background-color: #E6EEEE;
              border: 1px solid #FFFFFF;
              font-size: 8pt;
              padding: 4px;
          }
          table.tablesorter thead tr .header {
              background-image: url("bg.gif");
              background-position: right center;
              background-repeat: no-repeat;
              cursor: pointer;
          }
          table.tablesorter tbody td {
              background-color: #FFFFFF;
              color: #3D3D3D;
              padding: 4px;
              vertical-align: top;
          }
          table.tablesorter tbody tr.odd td {
              background-color: #F0F0F6;
          }
          table.tablesorter thead tr .headerSortUp {
              background-image: url("../images/asc.gif");
          }
          table.tablesorter thead tr .headerSortDown {
              background-image: url("../images/desc.gif");
          }
          table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
              background-color: #8DBDD8;
          }
          
          table.tablesorter tr:nth-child(even) {
          	background-color: #DDDDDD;
          }
          
          table.tablesorter tr {
          	border-bottom: 1px solid #CCCCCC;
          }
          
          /*
          * Upload tool
          */
          
          .upload-tool {
          	padding:10px;
              position:relative;
          }
          
          .upload-tool-help {
              position:absolute;
              left:765px;
              font-size: 0.7em;
              margin-top: 4px;
          }
          
          .dc-controlpanel .dc-controlpanel-header > * {
          	float:right;
          }
          
          .dc-controlpanel .dc-controlpanel-header  {
          	background-color: #444;
          	padding: 5px;
          	height:25px;
          }
          
          .dc-controlpanel input[type="checkbox"]  {
          	margin:0px 5px 0px 5px !important;
          }
          
          table.dc-acls td:first-child {
          	width:50%;
          }
          
          table.dc-acls td:last-child {
          	width:25% ;
          }
          
          .user, .group {
          	padding-left:20px;
          }
          
          .dc-graph {
          	width:150px;
          	height:150px;
          	display:inline-block;
          }
          
          .dc-graph-holder {
          	display:inline-block;
          	text-align: center;
          }
          
          .dc-graph-holder {
          	margin-left: 40px;
          
          }
           .history-panel #summaries-graph {
           	height:150px;
          	display:inline-block;
          
           }
          
           .history-panel .segment-content > * {
              width: 95%;
           }
          
           .history-panel #summaries-legend {
          	display:block;
          	color: #EEE;
          	padding:5px;
           }
           .history-panel #summaries-legend table {
           	border: 1px solid #555;
           }
          
          .history-panel #summaries-legend .legendLabel{
          	color: #EEE;
          }
          
          .history-panel #summaries-legend table {
          	width: 50px !important;
          }
          
          .history-panel h6 {
          	margin-bottom: 10px;
          }
          
          #streaming-pane > p {
          	margin-bottom: 20px;
          }
          
          #hlsSwitchControl {
          	border-bottom: 1px solid #555;
          	padding-bottom:10px;
          	margin-bottom:10px;
          	width:100%;
          	display: inline-block;
          	margin-top: 20px;
          
          }
          
          #hlsSwitchControl {
          	margin-top: 25px;
          }
          
          .streaming-switch-holder {
          	height:20px;
          	display:inline-block;
          	white-space: nowrap;
          	margin-bottom: 20px;
          }
          .streaming-switch-holder label {
          	font-size: 1.25em;
          }
          
          .streaming-switch {
          	display:inline-block;
          	font-size:0.7em;
          }
          
          .button-bar {
          	white-space: nowrap;
          }
          
          .object-name {
          	white-space: nowrap;
          	margin-bottom: 10px !important;
          }
          
          button#enable-streaming {
          	margin-top:10px;
          }
          
          button.add-space-button {
            display: none;
          }
          
          .dc-item-divider {
            background-color:#5b5b5b;
            padding:5px;
            font-weight: bold;
          
          }
          
          .dc-busy-holder {
              background: url('../images/wait.gif') no-repeat left center;
              display:inline-block;
              vertical-align:middle;
              height:20px;
              width:20px;
              min-width:30px;
              font-size: 10px;
              padding-left:20px;
          }
          
          div.snapshot.dc-item {
            padding: 5px 5px 0px 7px;
          }
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        24. GET https://dev.duracloud.org/duradmin/style/buttons.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (365 bytes)
          GET https://dev.duracloud.org/duradmin/style/buttons.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 8525
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"8525-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (8525 bytes)
          /* css classes for buttons and a tags as buttons */
          
          button::-moz-focus-inner
          {
          	border: none;  /* overrides extra padding in Firefox */
          	padding:0 !important;
          }
          
          button a
          {
          	text-decoration:none;
          }
          
          button,
          .button,
          .icon-link,
          .switch-holder,
          .switch
          {
          	font-family:Verdana, Helvetica, Sans-Serif;
          	font-size:11px;
          	font-style:normal;
          	white-space:nowrap;
          	width:auto;
          }
          
          button,
          .button,
          .icon-link,
          .switch
          {
          	color:#ccc;
          	display:inline-block;
          	position:relative;
          	overflow: visible; /* removes extra side padding in IE */
          	text-align:center;
          	text-decoration:none;
          	vertical-align:middle;
          }
          
          button,
          .button,
          .switch
          {
          	-moz-border-radius:5px;	
          	-webkit-border-radius:5px;
          	border-radius:5px;
          	border-width:1px;
          	border-style:solid;
          	border-color:#333;
          	padding:1px 10px 0 10px;
          
          }
          
          button,
          .button
          {	
          	background-color:#313131;
          	background: -moz-linear-gradient(top, #595959, #313131);
          	background: -webkit-gradient(linear, left top, left bottom, from(#595959), to(#313131)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF595959, endColorstr=#FF313131); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF59595, endColorstr=#FF313131)";	/* For Internet Explorer 8 */
          	cursor:pointer;
          	height:25px;
          	margin-right:2px !important;
          
          }
          
          .button
          {
          	padding-top:4px;
          	height:19px;
          }
          
          button,
          a.button,
          button.featured,
          a.button.featured
          { 
          	background-color:#bbb !important;
          	background: -moz-linear-gradient(top, #e4e4e4, #999999);
          	background: -webkit-gradient(linear, left top, left bottom, from(#e4e4e4), to(#999999)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFe4e4e4, endColorstr=#FF999999); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFe4e4e4, endColorstr=#FF999999)";	/* For Internet Explorer 8 */
          	color:#444 !important;
          }
          
          button.primary,
          .button.primary
          {
          
          	background-color:#2375b2;
          	background: -moz-linear-gradient(top, #37a9de, #2375b2);
          	background: -webkit-gradient(linear, left top, left bottom, from(#37a9de), to(#2375b2)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF37a9de, endColorstr=#FF2375b2); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF37a9de, endColorstr=#FF2375b2)";	/* For Internet Explorer 8 */
          	color:#ffffff !important;
              width:122px;
          }
          
          button.primary:hover,
          a.button.primary:hover
          {
          
          	background-color:#3793d6;
          	background: -moz-linear-gradient(top, #4db6e8, #3793d6);
          	background: -webkit-gradient(linear, left top, left bottom, from(#4db6e8), to(#3793d6)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF4db6e8, endColorstr=#FF3793d6); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF4db6e8, endColorstr=#FF3793d6)";	/* For Internet Explorer 8 */
          	border-color:#4db6e8;
          	color:#ffffff;
          }
          
          button.small,
          .button.small
          {
          	height:20px;
          }
          
          
          button:hover,
          a.button:hover,
          button.featured:hover,
          a.button.featured:hover
          { 
          	background-color:#c9c9c9 !important;
          	background: -moz-linear-gradient(top, #f8f8f8, #c9c9c9);
          	background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#c9c9c9)); 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFf8f8f8, endColorstr=#FFc9c9c9); /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFf8f8f8, endColorstr=#FFc9c9c9)";	/* For Internet Explorer 8 */
          	color:#000; 
          }
          
          
          button[disabled], button[disabled]:hover,
          .button[disabled], .button[disabled]:hover 
          
          {	
          	background-color:#515151 !important;
          	background: -moz-linear-gradient(top, #797979, #515151) !important;
          	background: -webkit-gradient(linear, left top, left bottom, from(#797979), to(#515151)) !important; 	/* For WebKit (Safari, Google Chrome etc) */
          	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF797979, endColorstr=#FF515151) !important; /* For Internet Explorer 5.5 - 7 */
          	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FF797979, endColorstr=#FF515151)" !important;	/* For Internet Explorer 8 */
          	margin-right:2px;
          	color: #333 !important;
          	border-color:#333 !important;
          	cursor: default;
          	pointer-events: none;
          	
          }
          
          
          button i,
          span.switch i,
          .button i,
          .icon-link i
          {
          	background-position:0 0;
          	background-repeat:no-repeat;
          	display:inline-block;
          	height:16px;
          	margin-top:-1px;
          	vertical-align:middle;
          	width:14px;
          }
          
          .icon-link:hover i
          {
          	background-position:left 0;
          }
          
          span.switch i, .button i { margin-top:0; }
          
          button i.pre,
          .button i.pre,
          .icon-link i,
          span.switch i.pre
          {
          	margin-left:-3px;
          	margin-right:5px;
          }
          
          button i.post,
          .button i.post,
          span.switch i.post
          {
          	margin-left:3px;
          	margin-right:-5px;
          }
          
          .icon-only
          {
          	padding-right:5px;
          }
          
          .icon-only .pre {
              margin-right:0;
              color: transparent;
          }
          
          
          /* SWTICHES *****************************************************/
          
          .switch-holder
          {
          	background-color:#545454;
          	-moz-border-radius:8px;	
          	-webkit-border-radius:8px;
          	border-radius:8px;
          	margin:20px 0;
          	padding:7px;
          }
          
          .switch { margin:0 }
          
          span.switch
          {
          	box-shadow:inset 0 0 3px #000000;
             -moz-box-shadow:inset 0 0 3px #000000;
             -webkit-box-shadow:inset 0 0 3px #000000;
          	height:19px;
          	padding-top:4px;
          }
          
          .switch.left
          {
          	-webkit-border-top-right-radius: 0px;
          	-webkit-border-bottom-right-radius: 0px;
          	-moz-border-radius-topright: 0px;
          	-moz-border-radius-bottomright: 0px;
          	border-top-right-radius: 0px;
          	border-bottom-right-radius: 0px;
          }
          
          .switch.right
          {
          	-webkit-border-top-left-radius: 0px;
          	-webkit-border-bottom-left-radius: 0px;
          	-moz-border-radius-topleft: 0px;
          	-moz-border-radius-bottomleft: 0px;
          	border-top-left-radius: 0px;
          	border-bottom-left-radius: 0px;
          }
          
          span.switch.right { border-left:none; }
          span.switch.left { border-right:none; }
          
          span.on
          {
          	background-color:#009900;
          	color:#66FF00;
          }
          
          span.off
          {
          	background-color:#990000;
          	color:#FF6600;
          }
          
          span.on i,
          span.off i,
          .icon-link i
          {
          	background-position:left -20px;
          }
          
          /* SPECIFIC BUTTONS *****************************************************/
          
          .plus { background-image:url(../images/icon_sm_plus.png); }
          .featured .plus { background-image:url(../images/icon_sm_plus_featured.png); }
          .pencil { background-image:url(../images/icon_sm_pencil.png); }
          .trash { background-image:url(../images/icon_sm_trash.png); }
          .copy { background-image:url(../images/icon_sm_copy.png); }
          .back { background-image:url(../images/icon_sm_back.png); }
          
          .x { background:url(../images/icon_sm_x.png); }
          .lock { background-image:url(../images/icon_sm_lock.png); }
          .unlock { background-image:url(../images/icon_sm_unlock.png); }
          .checkbox { background:url(../images/icon_sm_checkbox.png); }
          .view { background-image:url(../images/icon_sm_view.png); }
          .download { background-image:url(../images/icon_sm_download_featured.png); }
          .arw-down-blue { background:url(../images/icon_sm_arw_blue.gif) no-repeat top right; }
          .arw-down-liteblue { background-image:url(../images/icon_sm_arw_cyan.gif); }
          .arw-down-green { background:url(../images/icon_sm_arw_green.gif) no-repeat top right; }
          .outer .getstarted { background-image:url(../images/icon_sm_start_blue.gif); }
          .outer .help { background-image:url(../images/icon_sm_help_blue.gif); }
          .outer .logoff { background-image:url(../images/icon_sm_logoff_blue.gif); }
          .data-table { background-image:url(../images/icon_sm_table.png); }
          .user { background:url(../images/icon_sm_user.png) no-repeat; }
          .group { background:url(../images/icon_sm_group.png) no-repeat; }
          .group-public { background:url(../images/icon_sm_group_public.png) no-repeat; }
          
          .refresh { background:url(../images/icon_sm_refresh.png) no-repeat; }
          
          /* BUTTONS IN SPECIFIC AREAS *******************************/
          .dc-item button
          {
          	height:auto;
          }
          
          button#recount {
              float: right;
          }
          /* ICON LINKS **********************************************/
          
          .icon-link
          {
          	margin-left:10px;
          }
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        25. GET https://dev.duracloud.org/duradmin/style/dialogs.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (365 bytes)
          GET https://dev.duracloud.org/duradmin/style/dialogs.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 4481
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"4481-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (4481 bytes)
          /* Style for Duradmin dialogs
          *  Created by Charles Hacskaylo
          *  Extends jquery-ui.css
          */
          
          /* DIALOG BOX *******************************/
          
          
          .ui-dialog
          {
          	-moz-border-radius:5px;
          	border-radius:5px;
          	background:url("../images/bg_L1.png") no-repeat center top #777;
          	border:1px solid #333;
          	color:#ccc;
          	font-size:13px;
          	overflow:hidden;
          	padding:20px;
          	position:absolute;
          }
          
          .ui-dialog-buttonpane
          {
          	text-align:right;
          }
          
          .ui-button
          {
          	background:url(../images/btn_dialog_std_90.png) no-repeat;
          	border:none;
          	color:#000;
          	font-size:13px;
          	height:28px;
          	margin-left:10px;
          	padding:0;
          	text-align:center;
          	width:90px;
          }
          
          .ui-button span
          {
          	display:block;
          	margin-top:-4px;
          }
          
          .ui-button:hover
          {
          	background-position:bottom;
          }
          
          .ui-dialog h1
          {
          	color:#bbb;
          	margin-bottom:5px;
          }
          
          .hint
          {
          	font-size:13px;
          }
          
          .ui-dialog .hint { 	color:#999; }
          .ui-dialog div.hint
          {
          	-moz-border-radius:5px;	
          	-webkit-border-radius:5px;
          	border-radius:5px;
          	background-color:#585B5E;
          	margin:10px 0;
          	padding:10px;
          }
          
          .ui-dialog div.hint h2 { color:#bbb; }
          
          .dialog-open {
          	border:1px solid  red !important;
          }
          
          .dialog-closed {
          	border:1px solid  blue !important;
          }
          
          .ui-dialog label.error
          {
          	/*background-color:#cc0000;*/
          	color:#ffcc00;
          	font-size:11px;
          	margin:1px 0 0 2px;
          	padding:1px 5px;
          }
          
          .ui-dialog-content
          {
          
          }
          
          .ui-dialog-buttonpane
          {
          
          }
          
          .ui-dialog .dc-item-list-wrapper
          {
          	background-color:#575757;
          }
          
          .ui-dialog .dc-item,
          .ui-dialog .dc-item td
          {
          	border-color:#666
          }
          
          .ui-dialog .dc-item,
          .ui-dialog .dc-item td
          {
          	color:#ccc;
          }
          
          .ui-dialog .dc-item:hover,
          .ui-dialog .dc-item:hover td
          {
          	background-color:#666;
          	color:#fff;
          }
          
          .ui-dialog .dialog-detail
          {
          	padding:0 10px;
          }
          
          /* SPECIFIC DIALOGS *************************/
          #available-services-dialog
          {
          	margin-bottom:10px;
          	overflow: auto !important;
          }
          
          
          #dc-item-list-wrapper,
          #dc-service-detail-wrapper
          {
          	float:left;
          	margin-right:10px;
          	width:300px !important;
          }
          
          /* UPLOAD STATUS DIALOG *************************/
          #upload-viewer{
          	height:430px;
          	overflow:auto;
          }
          
          #upload-viewer label:after{
           content: ':';
          }
          
          #upload-list-wrapper
          {
          	padding-right:10px;
          }
          
          .ui-dialog-buttonpane .dialog-info {
            float:left;   
            padding:10px;
            display:inline;
            font-size: 14px;
          }
          
          .dialog-info a{
            color: #ccc !important;
          }
          
          .upload-thumbnail {
            margin-top: 10px; 
            height:50px;
          }
          .upload-item 
          {
          	border-bottom:1px solid #555;
          	margin-bottom:5px;
          	padding:10px 0;
          	
          }
          
          #upload-option-divider {
            color: green;
            font-weight: bold;
            font-size: 30px;
            text-align: center;
            margin: 20px 0px 40px 0px;
          }
          
          #single-upload-1 label {
              width: 102px;
          }
          
          #single-upload-1  input {
              width: 350px;
          }
          
          #single-upload-2 {
            margin-top: 20px;
            text-align:center;
          }
          
          button#upload-another {
            margin-bottom:10px;
          }
          
          #drop-preview label {
              width: 102px;
          }
          
          #drop-preview input {
              width: 235px;
          }
          
          #drop-preview button.trashbutton {
              margin-top: -3px;
              margin-left: 5px;
          }
          
          .upload-item > * {
            margin-right: 5px;
          }
          
          .upload-item a {
            color:#eee;
          }
          
          
          #drop-target {
            border: 5px dashed #ccc;
            width: 95%;
            min-height: 50px;
            margin: 20px auto;
            padding:20px 0px;
            text-align: center;
            font-size: 20px;
            
          }
          
          #drop-target.hover {
            border: 5px dashed #0c0;
          }
          
          #drop-target img {
            display: block;
            margin: 10px auto;
          }
          
          #drop-target p {
            margin: 10px;
            font-size: 20px;
          }
          
          progress {
            width: 100%;
            margin: 10px 0px;
          }
          
          progress:after {
            content: '%';
          }
          /* OVERLAY **********************************/
          .ui-widget-overlay
          {
          	background:none;
          	background-color:#fff;
          	left:0;
          	opacity:0.2;
          	position:absolute;
          	top:0;
          }
          
          /* FORM FIELDS ***************************/
          /* Used by dialog boxes and login screen */
          
          .form-fields { overflow:auto; }
          .h400 { height:400px; }
          
          .form-fields
          {
          	font-size:14px;
          }
          
          .form-fields label
          {
          	color:#ccc;
          	display:inline-block;
          	float:left;
          	line-height:22px;
          	padding-right:10px;
          	width:130px;
          	white-space:normal;
          }
          
          .form-fields label.error
          {
              width:97%;
          }
          
          .form-fields .field
          {
          	display:inline-block;
          	float:left;
          }
          
          .form-fields input.field,
          .form-fields select.field,
          .form-fields textarea.field
          {
          	background-color:#585b5e; /* 484747 */
          	border:1px solid #36383a; /* 727576 */
          	border-bottom-color:#727576;
          	color:#ccc;
          	font-size:14px;
          	padding:3px;
          }
          
          select.field
          {
          }
          
          
          .form-fields li
          {
          	padding:5px 0;
          	white-space:nowrap;
          }
          
          .form-fields li.row
          {
          	border-top:1px solid #666;
          }
          
          .form-fields a.helper-link
          {
          	color:#8a8a8a;
          	font-size:11px;
          }
          
          .form-fields a:hover
          {
          	color:#ccc;
          }
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        26. GET https://dev.duracloud.org/duradmin/style/flex.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (362 bytes)
          GET https://dev.duracloud.org/duradmin/style/flex.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (433 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 290
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"290-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (290 bytes)
          /* FLEX BASE CLASSES *********************************/
          
          .flex a,
          .flex,
          .flex span
          {
          	color:#ccc;
          	display:inline-block;
          	height:24px;
          	font-size:11px;
          	line-height:22px;
          	text-decoration:none;
          }
          
          .flex a,
          .flex
          {
          	padding-left:10px;
          }
          
          .flex span
          {
          	cursor:pointer;
          	padding-right:10px;
          }
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        27. GET https://dev.duracloud.org/duradmin/style/jquery-ui.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/style/jquery-ui.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (437 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 34214
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"34214-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (34214 bytes)
          /*
           * jQuery UI CSS Framework 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Theming/API
           */
          
          /* Layout helpers
          ----------------------------------*/
          .ui-helper-hidden { display: none; }
          .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
          .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
          .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
          .ui-helper-clearfix { display: inline-block; }
          /* required comment for clearfix to work in Opera \*/
          * html .ui-helper-clearfix { height:1%; }
          .ui-helper-clearfix { display:block; }
          /* end clearfix */
          .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
          
          
          /* Interaction Cues
          ----------------------------------*/
          .ui-state-disabled { cursor: default !important; }
          
          
          /* Icons
          ----------------------------------*/
          
          /* states and images */
          .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
          
          
          /* Misc visuals
          ----------------------------------*/
          
          /* Overlays */
          .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
          
          
          /*
           * jQuery UI CSS Framework 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Theming/API
           *
           * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
           */
          
          
          /* Component containers
          ----------------------------------*/
          .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
          .ui-widget .ui-widget { font-size: 1em; }
          .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
          /*.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }*/
          .ui-widget-content a { color: #222222; }
          .ui-widget-header { 
          	/*
          	 border: 1px solid #aaaaaa;
          	 background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; 
          	*/
          }
          .ui-widget-header a { color: #222222; }
          
          /* Interaction states
          ----------------------------------*/
          .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { 
          	border: 1px solid #7e7e7e; 
          	background: #6e6e6e url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; 
          	font-weight: normal; color: #AAAAAA; 
          }
          .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { 
          	color: #AAAAAA; text-decoration: none; 
          	
          }
          .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
          .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
          .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { 
          	border: 1px solid #aaaaaa; 
          	font-weight: normal; color: #212121; 
          	background-color: #9e9e9e;
          }
          .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
          .ui-widget :active { outline: none; }
          
          /* Interaction Cues
          ----------------------------------*/
          .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
          .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
          .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
          .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
          .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
          .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
          .ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
          .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
          
          /* Icons
          ----------------------------------*/
          
          /* states and images */
          .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
          .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
          .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
          .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
          .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
          .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
          .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
          .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
          
          /* positioning */
          .ui-icon-carat-1-n { background-position: 0 0; }
          .ui-icon-carat-1-ne { background-position: -16px 0; }
          .ui-icon-carat-1-e { background-position: -32px 0; }
          .ui-icon-carat-1-se { background-position: -48px 0; }
          .ui-icon-carat-1-s { background-position: -64px 0; }
          .ui-icon-carat-1-sw { background-position: -80px 0; }
          .ui-icon-carat-1-w { background-position: -96px 0; }
          .ui-icon-carat-1-nw { background-position: -112px 0; }
          .ui-icon-carat-2-n-s { background-position: -128px 0; }
          .ui-icon-carat-2-e-w { background-position: -144px 0; }
          .ui-icon-triangle-1-n { background-position: 0 -16px; }
          .ui-icon-triangle-1-ne { background-position: -16px -16px; }
          .ui-icon-triangle-1-e { background-position: -32px -16px; }
          .ui-icon-triangle-1-se { background-position: -48px -16px; }
          .ui-icon-triangle-1-s { background-position: -64px -16px; }
          .ui-icon-triangle-1-sw { background-position: -80px -16px; }
          .ui-icon-triangle-1-w { background-position: -96px -16px; }
          .ui-icon-triangle-1-nw { background-position: -112px -16px; }
          .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
          .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
          .ui-icon-arrow-1-n { background-position: 0 -32px; }
          .ui-icon-arrow-1-ne { background-position: -16px -32px; }
          .ui-icon-arrow-1-e { background-position: -32px -32px; }
          .ui-icon-arrow-1-se { background-position: -48px -32px; }
          .ui-icon-arrow-1-s { background-position: -64px -32px; }
          .ui-icon-arrow-1-sw { background-position: -80px -32px; }
          .ui-icon-arrow-1-w { background-position: -96px -32px; }
          .ui-icon-arrow-1-nw { background-position: -112px -32px; }
          .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
          .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
          .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
          .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
          .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
          .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
          .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
          .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
          .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
          .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
          .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
          .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
          .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
          .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
          .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
          .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
          .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
          .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
          .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
          .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
          .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
          .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
          .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
          .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
          .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
          .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
          .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
          .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
          .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
          .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
          .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
          .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
          .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
          .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
          .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
          .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
          .ui-icon-arrow-4 { background-position: 0 -80px; }
          .ui-icon-arrow-4-diag { background-position: -16px -80px; }
          .ui-icon-extlink { background-position: -32px -80px; }
          .ui-icon-newwin { background-position: -48px -80px; }
          .ui-icon-refresh { background-position: -64px -80px; }
          .ui-icon-shuffle { background-position: -80px -80px; }
          .ui-icon-transfer-e-w { background-position: -96px -80px; }
          .ui-icon-transferthick-e-w { background-position: -112px -80px; }
          .ui-icon-folder-collapsed { background-position: 0 -96px; }
          .ui-icon-folder-open { background-position: -16px -96px; }
          .ui-icon-document { background-position: -32px -96px; }
          .ui-icon-document-b { background-position: -48px -96px; }
          .ui-icon-note { background-position: -64px -96px; }
          .ui-icon-mail-closed { background-position: -80px -96px; }
          .ui-icon-mail-open { background-position: -96px -96px; }
          .ui-icon-suitcase { background-position: -112px -96px; }
          .ui-icon-comment { background-position: -128px -96px; }
          .ui-icon-person { background-position: -144px -96px; }
          .ui-icon-print { background-position: -160px -96px; }
          .ui-icon-trash { background-position: -176px -96px; }
          .ui-icon-locked { background-position: -192px -96px; }
          .ui-icon-unlocked { background-position: -208px -96px; }
          .ui-icon-bookmark { background-position: -224px -96px; }
          .ui-icon-tag { background-position: -240px -96px; }
          .ui-icon-home { background-position: 0 -112px; }
          .ui-icon-flag { background-position: -16px -112px; }
          .ui-icon-calendar { background-position: -32px -112px; }
          .ui-icon-cart { background-position: -48px -112px; }
          .ui-icon-pencil { background-position: -64px -112px; }
          .ui-icon-clock { background-position: -80px -112px; }
          .ui-icon-disk { background-position: -96px -112px; }
          .ui-icon-calculator { background-position: -112px -112px; }
          .ui-icon-zoomin { background-position: -128px -112px; }
          .ui-icon-zoomout { background-position: -144px -112px; }
          .ui-icon-search { background-position: -160px -112px; }
          .ui-icon-wrench { background-position: -176px -112px; }
          .ui-icon-gear { background-position: -192px -112px; }
          .ui-icon-heart { background-position: -208px -112px; }
          .ui-icon-star { background-position: -224px -112px; }
          .ui-icon-link { background-position: -240px -112px; }
          .ui-icon-cancel { background-position: 0 -128px; }
          .ui-icon-plus { background-position: -16px -128px; }
          .ui-icon-plusthick { background-position: -32px -128px; }
          .ui-icon-minus { background-position: -48px -128px; }
          .ui-icon-minusthick { background-position: -64px -128px; }
          .ui-icon-close { background-position: -80px -128px; }
          .ui-icon-closethick { background-position: -96px -128px; }
          .ui-icon-key { background-position: -112px -128px; }
          .ui-icon-lightbulb { background-position: -128px -128px; }
          .ui-icon-scissors { background-position: -144px -128px; }
          .ui-icon-clipboard { background-position: -160px -128px; }
          .ui-icon-copy { background-position: -176px -128px; }
          .ui-icon-contact { background-position: -192px -128px; }
          .ui-icon-image { background-position: -208px -128px; }
          .ui-icon-video { background-position: -224px -128px; }
          .ui-icon-script { background-position: -240px -128px; }
          .ui-icon-alert { background-position: 0 -144px; }
          .ui-icon-info { background-position: -16px -144px; }
          .ui-icon-notice { background-position: -32px -144px; }
          .ui-icon-help { background-position: -48px -144px; }
          .ui-icon-check { background-position: -64px -144px; }
          .ui-icon-bullet { background-position: -80px -144px; }
          .ui-icon-radio-off { background-position: -96px -144px; }
          .ui-icon-radio-on { background-position: -112px -144px; }
          .ui-icon-pin-w { background-position: -128px -144px; }
          .ui-icon-pin-s { background-position: -144px -144px; }
          .ui-icon-play { background-position: 0 -160px; }
          .ui-icon-pause { background-position: -16px -160px; }
          .ui-icon-seek-next { background-position: -32px -160px; }
          .ui-icon-seek-prev { background-position: -48px -160px; }
          .ui-icon-seek-end { background-position: -64px -160px; }
          .ui-icon-seek-start { background-position: -80px -160px; }
          /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
          .ui-icon-seek-first { background-position: -80px -160px; }
          .ui-icon-stop { background-position: -96px -160px; }
          .ui-icon-eject { background-position: -112px -160px; }
          .ui-icon-volume-off { background-position: -128px -160px; }
          .ui-icon-volume-on { background-position: -144px -160px; }
          .ui-icon-power { background-position: 0 -176px; }
          .ui-icon-signal-diag { background-position: -16px -176px; }
          .ui-icon-signal { background-position: -32px -176px; }
          .ui-icon-battery-0 { background-position: -48px -176px; }
          .ui-icon-battery-1 { background-position: -64px -176px; }
          .ui-icon-battery-2 { background-position: -80px -176px; }
          .ui-icon-battery-3 { background-position: -96px -176px; }
          .ui-icon-circle-plus { background-position: 0 -192px; }
          .ui-icon-circle-minus { background-position: -16px -192px; }
          .ui-icon-circle-close { background-position: -32px -192px; }
          .ui-icon-circle-triangle-e { background-position: -48px -192px; }
          .ui-icon-circle-triangle-s { background-position: -64px -192px; }
          .ui-icon-circle-triangle-w { background-position: -80px -192px; }
          .ui-icon-circle-triangle-n { background-position: -96px -192px; }
          .ui-icon-circle-arrow-e { background-position: -112px -192px; }
          .ui-icon-circle-arrow-s { background-position: -128px -192px; }
          .ui-icon-circle-arrow-w { background-position: -144px -192px; }
          .ui-icon-circle-arrow-n { background-position: -160px -192px; }
          .ui-icon-circle-zoomin { background-position: -176px -192px; }
          .ui-icon-circle-zoomout { background-position: -192px -192px; }
          .ui-icon-circle-check { background-position: -208px -192px; }
          .ui-icon-circlesmall-plus { background-position: 0 -208px; }
          .ui-icon-circlesmall-minus { background-position: -16px -208px; }
          .ui-icon-circlesmall-close { background-position: -32px -208px; }
          .ui-icon-squaresmall-plus { background-position: -48px -208px; }
          .ui-icon-squaresmall-minus { background-position: -64px -208px; }
          .ui-icon-squaresmall-close { background-position: -80px -208px; }
          .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
          .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
          .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
          .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
          .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
          .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
          
          
          /* Misc visuals
          ----------------------------------*/
          
          /* Corner radius */
          .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
          .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
          .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
          .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
          .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
          .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
          .ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
          .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
          .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
          
          /* Overlays */
          .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
          .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
           * jQuery UI Resizable 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizable#theming
           */
          .ui-resizable { position: relative;}
          .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;
          	/* http://bugs.jqueryui.com/ticket/7233
          	 - Resizable: resizable handles fail to work in IE if transparent and content overlaps
          	*/
          	background-image:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=);
          }
          .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
          .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
          .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
          .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
          .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
          .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
          .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
          .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
          .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
           * jQuery UI Selectable 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectable#theming
           */
          .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
          /*
           * jQuery UI Accordion 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion#theming
           */
          /* IE/Win - Fix animation bug - #4615 */
          .ui-accordion { width: 100%; }
          .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
          .ui-accordion .ui-accordion-li-fix { display: inline; }
          .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
          .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
          .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
          .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
          .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
          .ui-accordion .ui-accordion-content-active { display: block; }
          /*
           * jQuery UI Autocomplete 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete#theming
           */
          .ui-autocomplete { position: absolute; cursor: default; }	
          
          /* workarounds */
          * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
          
          /*
           * jQuery UI Menu 1.8.13
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu#theming
           */
          .ui-menu {
          	list-style:none;
          	padding: 2px;
          	margin: 0;
          	display:block;
          	float: left;
          }
          .ui-menu .ui-menu {
          	margin-top: -3px;
          }
          .ui-menu .ui-menu-item {
          	margin:0;
          	padding: 0;
          	zoom: 1;
          	float: left;
          	clear: left;
          	width: 100%;
          }
          .ui-menu .ui-menu-item a {
          	text-decoration:none;
          	display:block;
          	padding:.2em .4em;
          	line-height:1.5;
          	zoom:1;
          }
          .ui-menu .ui-menu-item a.ui-state-hover,
          .ui-menu .ui-menu-item a.ui-state-active {
          	font-weight: normal;
          	margin: -1px;
          }
          /*
           * jQuery UI Button 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button#theming
           */
          .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
          .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
          button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
          .ui-button-icons-only { width: 3.4em; } 
          button.ui-button-icons-only { width: 3.7em; } 
          
          /*button text element */
          .ui-button .ui-button-text { display: block; line-height: 1.4;  }
          .ui-button-text-only .ui-button-text { padding: .4em 1em; }
          .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
          .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
          .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
          .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
          /* no icon support for input elements, provide padding by default */
          input.ui-button { padding: .4em 1em; }
          
          /*button icon element(s) */
          .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
          .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
          .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
          .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
          .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
          
          /*button sets*/
          .ui-buttonset { margin-right: 7px; }
          .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
          
          /* workarounds */
          button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
          /*
           * jQuery UI Dialog 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog#theming
           */
          .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
          .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
          .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 
          .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
          .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
          .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
          .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
          .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
          .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
          .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
          .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
          .ui-draggable .ui-dialog-titlebar { cursor: move; }
          /*
           * jQuery UI Slider 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider#theming
           */
          .ui-slider { position: relative; text-align: left;}
          .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
          .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
          .ui-slider-horizontal { height: .8em; }
          .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
          .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
          .ui-slider-horizontal .ui-slider-range-min { left: 0; }
          .ui-slider-horizontal .ui-slider-range-max { right: 0; }
          
          .ui-slider-vertical { width: .8em; height: 100px; }
          .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
          .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
          .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
          .ui-slider-vertical .ui-slider-range-max { top: 0; }/*
          
          
           * jQuery UI Tabs 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs#theming
           */
          .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
          .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
          .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
          .ui-tabs .ui-tabs-nav li a { float: left; padding: .12em .25em; text-decoration: none; font-size:0.9em}
          .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
          .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
          .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
          .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 0.5em 0.7em; background: none; }
          .ui-tabs .ui-tabs-hide { display: none !important; }
          /*
           * jQuery UI Datepicker 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker#theming
           */
          .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
          .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
          .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
          .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
          .ui-datepicker .ui-datepicker-prev { left:2px; }
          .ui-datepicker .ui-datepicker-next { right:2px; }
          .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
          .ui-datepicker .ui-datepicker-next-hover { right:1px; }
          .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
          .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
          .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
          .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
          .ui-datepicker select.ui-datepicker-month, 
          .ui-datepicker select.ui-datepicker-year { width: 49%;}
          .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
          .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
          .ui-datepicker td { border: 0; padding: 1px; }
          .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
          .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
          .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
          .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
          
          /* with multiple calendars */
          .ui-datepicker.ui-datepicker-multi { width:auto; }
          .ui-datepicker-multi .ui-datepicker-group { float:left; }
          .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
          .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
          .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
          .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
          .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
          .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
          .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
          .ui-datepicker-row-break { clear:both; width:100%; }
          
          /* RTL support */
          .ui-datepicker-rtl { direction: rtl; }
          .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
          .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
          .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
          .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
          .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
          .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
          .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
          .ui-datepicker-rtl .ui-datepicker-group { float:right; }
          .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
          .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
          
          /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
          .ui-datepicker-cover {
              display: none; /*sorry for IE5*/
              display/**/: block; /*sorry for IE5*/
              position: absolute; /*must have*/
              z-index: -1; /*must have*/
              filter: mask(); /*must have*/
              top: -4px; /*must have*/
              left: -4px; /*must have*/
              width: 200px; /*must have*/
              height: 200px; /*must have*/
          }/*
           * jQuery UI Progressbar 1.8.13
           *
           * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar#theming
           */
          .ui-progressbar { height:2em; text-align: left; }
          .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
          
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

        28. GET https://dev.duracloud.org/duradmin/style/login.css
          Alert tags
          Alert description

          The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.

          Other info

          This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.

          At "High" threshold this scan rule will not alert on client or server error responses.

          Request
          Request line and header section (363 bytes)
          GET https://dev.duracloud.org/duradmin/style/login.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (435 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: text/css
          Content-Length: 1364
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"1364-1618991490000"
          Last-Modified: Wed, 21 Apr 2021 07:51:30 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (1364 bytes)
          #login-wrapper
          {
          	position:absolute;
          	top:20%;
          	width:100%;
          }
          
          
          #login-header
          {
          	margin:0 0 20px 20px;
          }
          
          #login-links
          {
              float: right;
              text-decoration: none;
              margin-top: 10px;
              margin-right: 12px;
              font-size: 14px;
          }
          
          #login-links a
          {
              text-decoration: none;
          }
          
          #dc-logo,
          #dc-app-title
          {
          	height:60px;
          }
          
          #dc-logo
          {
          	background-image:url(../images/logo_top_duracloud_lg.png);
          	width:152px;
          }
          
          
          #dc-app-title
          {
          	background-image:url(../images/app_title_lg.png);
          	width:330px;
          
          }
          
          #login-content,
          #login-footer
          {
          
          	min-width:750px;
          	width:75%;
          
          }
          
          #login-content
          {
          	padding:50px 10px;
          }
          
          #login-content .error
          {
          	font-size:13px;
          }
          
          #login-content h1
          {
          	color:#666;
          	display:block;
          	margin-left:30px;
          	width:100px;
          }
          
          #login-footer
          {
          	background-position:right -30px;
          }
          
          #login-wrapper .footer-content { padding-top:20px; }
          
          
          #form-fields #button-login,
          #form-fields #button-login span
          {
          	background-image:url(../images/btn_login.gif);
          	color:#fff !important;
          	height:28px;
          	line-height:25px;
          	font-size: 14px;
          }
          
          
          #form-fields #button-login span
          {
          	padding-right:50px;
          }
          
          
          /* LOGIN STYLES ****************************/
          
          .ui-dialog fieldset
          {
          	padding:20px 0;
          }
          
          
          #login-content .form-fields
          {
          	margin-right:20%;
          	width:350px;
          }
          
          #login-content label
          {
              text-align: right;
          }
          
          #login-content .form-fields .field
          {
          	float:right;
          	width:200px;
          }
          
          Parameter
          X-Content-Type-Options
          Solution

          Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.

          If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.

  3. Risk=Low, Confidence=Low (7)

    1. https://dev.duracloud.org (7)

      1. Timestamp Disclosure - Unix (7)
        1. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          A timestamp was disclosed by the application/web server - Unix

          Other info

          0123456789, which evaluates to: 1973-11-29 16:33:09

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          0123456789
          Solution

          Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

        2. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          A timestamp was disclosed by the application/web server - Unix

          Other info

          10000000, which evaluates to: 1970-04-26 13:46:40

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          10000000
          Solution

          Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

        3. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          A timestamp was disclosed by the application/web server - Unix

          Other info

          86400000, which evaluates to: 1972-09-26 20:00:00

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          86400000
          Solution

          Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

        4. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js
          Alert tags
          Alert description

          A timestamp was disclosed by the application/web server - Unix

          Other info

          2147483647, which evaluates to: 2038-01-18 22:14:07

          Request
          Request line and header section (397 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 37133
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"37133-1268175436000"
          Last-Modified: Tue, 09 Mar 2010 22:57:16 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (37133 bytes)
          /*
           * jQuery validation plug-in 1.7
           *
           * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
           * http://docs.jquery.com/Plugins/Validation
           *
           * Copyright (c) 2006 - 2008 Jörn Zaefferer
           *
           * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          $.extend($.fn, {
          	// http://docs.jquery.com/Plugins/Validation/validate
          	validate: function( options ) {
          
          		// if nothing is selected, return nothing; can't chain anyway
          		if (!this.length) {
          			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
          			return;
          		}
          
          		// check if a validator for this form was already created
          		var validator = $.data(this[0], 'validator');
          		if ( validator ) {
          			return validator;
          		}
          		
          		validator = new $.validator( options, this[0] );
          		$.data(this[0], 'validator', validator); 
          		
          		if ( validator.settings.onsubmit ) {
          		
          			// allow suppresing validation by adding a cancel class to the submit button
          			this.find("input, button").filter(".cancel").click(function() {
          				validator.cancelSubmit = true;
          			});
          			
          			// when a submitHandler is used, capture the submitting button
          			if (validator.settings.submitHandler) {
          				this.find("input, button").filter(":submit").click(function() {
          					validator.submitButton = this;
          				});
          			}
          		
          			// validate the form on submit
          			this.submit( function( event ) {
          				if ( validator.settings.debug )
          					// prevent form submit to be able to see console output
          					event.preventDefault();
          					
          				function handle() {
          					if ( validator.settings.submitHandler ) {
          						if (validator.submitButton) {
          							// insert a hidden input as a replacement for the missing submit button
          							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
          						}
          						validator.settings.submitHandler.call( validator, validator.currentForm );
          						if (validator.submitButton) {
          							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
          							hidden.remove();
          						}
          						return false;
          					}
          					return true;
          				}
          					
          				// prevent submit for invalid forms or custom submit handlers
          				if ( validator.cancelSubmit ) {
          					validator.cancelSubmit = false;
          					return handle();
          				}
          				if ( validator.form() ) {
          					if ( validator.pendingRequest ) {
          						validator.formSubmitted = true;
          						return false;
          					}
          					return handle();
          				} else {
          					validator.focusInvalid();
          					return false;
          				}
          			});
          		}
          		
          		return validator;
          	},
          	// http://docs.jquery.com/Plugins/Validation/valid
          	valid: function() {
                  if ( $(this[0]).is('form')) {
                      return this.validate().form();
                  } else {
                      var valid = true;
                      var validator = $(this[0].form).validate();
                      this.each(function() {
          				valid &= validator.element(this);
                      });
                      return valid;
                  }
              },
          	// attributes: space seperated list of attributes to retrieve and remove
          	removeAttrs: function(attributes) {
          		var result = {},
          			$element = this;
          		$.each(attributes.split(/\s/), function(index, value) {
          			result[value] = $element.attr(value);
          			$element.removeAttr(value);
          		});
          		return result;
          	},
          	// http://docs.jquery.com/Plugins/Validation/rules
          	rules: function(command, argument) {
          		var element = this[0];
          		
          		if (command) {
          			var settings = $.data(element.form, 'validator').settings;
          			var staticRules = settings.rules;
          			var existingRules = $.validator.staticRules(element);
          			switch(command) {
          			case "add":
          				$.extend(existingRules, $.validator.normalizeRule(argument));
          				staticRules[element.name] = existingRules;
          				if (argument.messages)
          					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
          				break;
          			case "remove":
          				if (!argument) {
          					delete staticRules[element.name];
          					return existingRules;
          				}
          				var filtered = {};
          				$.each(argument.split(/\s/), function(index, method) {
          					filtered[method] = existingRules[method];
          					delete existingRules[method];
          				});
          				return filtered;
          			}
          		}
          		
          		var data = $.validator.normalizeRules(
          		$.extend(
          			{},
          			$.validator.metadataRules(element),
          			$.validator.classRules(element),
          			$.validator.attributeRules(element),
          			$.validator.staticRules(element)
          		), element);
          		
          		// make sure required is at front
          		if (data.required) {
          			var param = data.required;
          			delete data.required;
          			data = $.extend({required: param}, data);
          		}
          		
          		return data;
          	}
          });
          
          // Custom selectors
          $.extend($.expr[":"], {
          	// http://docs.jquery.com/Plugins/Validation/blank
          	blank: function(a) {return !$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/filled
          	filled: function(a) {return !!$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/unchecked
          	unchecked: function(a) {return !a.checked;}
          });
          
          // constructor for validator
          $.validator = function( options, form ) {
          	this.settings = $.extend( true, {}, $.validator.defaults, options );
          	this.currentForm = form;
          	this.init();
          };
          
          $.validator.format = function(source, params) {
          	if ( arguments.length == 1 ) 
          		return function() {
          			var args = $.makeArray(arguments);
          			args.unshift(source);
          			return $.validator.format.apply( this, args );
          		};
          	if ( arguments.length > 2 && params.constructor != Array  ) {
          		params = $.makeArray(arguments).slice(1);
          	}
          	if ( params.constructor != Array ) {
          		params = [ params ];
          	}
          	$.each(params, function(i, n) {
          		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
          	});
          	return source;
          };
          
          $.extend($.validator, {
          	
          	defaults: {
          		messages: {},
          		groups: {},
          		rules: {},
          		errorClass: "error",
          		validClass: "valid",
          		errorElement: "label",
          		focusInvalid: true,
          		errorContainer: $( [] ),
          		errorLabelContainer: $( [] ),
          		onsubmit: true,
          		ignore: [],
          		ignoreTitle: false,
          		onfocusin: function(element) {
          			this.lastActive = element;
          				
          			// hide error label and remove error class on focus if enabled
          			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
          				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
          				this.errorsFor(element).hide();
          			}
          		},
          		onfocusout: function(element) {
          			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
          				this.element(element);
          			}
          		},
          		onkeyup: function(element) {
          			if ( element.name in this.submitted || element == this.lastElement ) {
          				this.element(element);
          			}
          		},
          		onclick: function(element) {
          			// click on selects, radiobuttons and checkboxes
          			if ( element.name in this.submitted )
          				this.element(element);
          			// or option elements, check parent select in that case
          			else if (element.parentNode.name in this.submitted)
          				this.element(element.parentNode);
          		},
          		highlight: function( element, errorClass, validClass ) {
          			$(element).addClass(errorClass).removeClass(validClass);
          		},
          		unhighlight: function( element, errorClass, validClass ) {
          			$(element).removeClass(errorClass).addClass(validClass);
          		}
          	},
          
          	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
          	setDefaults: function(settings) {
          		$.extend( $.validator.defaults, settings );
          	},
          
          	messages: {
          		required: "This field is required.",
          		remote: "Please fix this field.",
          		email: "Please enter a valid email address.",
          		url: "Please enter a valid URL.",
          		date: "Please enter a valid date.",
          		dateISO: "Please enter a valid date (ISO).",
          		number: "Please enter a valid number.",
          		digits: "Please enter only digits.",
          		creditcard: "Please enter a valid credit card number.",
          		equalTo: "Please enter the same value again.",
          		accept: "Please enter a value with a valid extension.",
          		maxlength: $.validator.format("Please enter no more than {0} characters."),
          		minlength: $.validator.format("Please enter at least {0} characters."),
          		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
          		range: $.validator.format("Please enter a value between {0} and {1}."),
          		max: $.validator.format("Please enter a value less than or equal to {0}."),
          		min: $.validator.format("Please enter a value greater than or equal to {0}.")
          	},
          	
          	autoCreateRanges: false,
          	
          	prototype: {
          		
          		init: function() {
          			this.labelContainer = $(this.settings.errorLabelContainer);
          			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
          			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
          			this.submitted = {};
          			this.valueCache = {};
          			this.pendingRequest = 0;
          			this.pending = {};
          			this.invalid = {};
          			this.reset();
          			
          			var groups = (this.groups = {});
          			$.each(this.settings.groups, function(key, value) {
          				$.each(value.split(/\s/), function(index, name) {
          					groups[name] = key;
          				});
          			});
          			var rules = this.settings.rules;
          			$.each(rules, function(key, value) {
          				rules[key] = $.validator.normalizeRule(value);
          			});
          			
          			function delegate(event) {
          				var validator = $.data(this[0].form, "validator"),
          					eventType = "on" + event.type.replace(/^validate/, "");
          				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
          			}
          			$(this.currentForm)
          				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
          				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);
          
          			if (this.settings.invalidHandler)
          				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/form
          		form: function() {
          			this.checkForm();
          			$.extend(this.submitted, this.errorMap);
          			this.invalid = $.extend({}, this.errorMap);
          			if (!this.valid())
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          			this.showErrors();
          			return this.valid();
          		},
          		
          		checkForm: function() {
          			this.prepareForm();
          			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
          				this.check( elements[i] );
          			}
          			return this.valid(); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/element
          		element: function( element ) {
          			element = this.clean( element );
          			this.lastElement = element;
          			this.prepareElement( element );
          			this.currentElements = $(element);
          			var result = this.check( element );
          			if ( result ) {
          				delete this.invalid[element.name];
          			} else {
          				this.invalid[element.name] = true;
          			}
          			if ( !this.numberOfInvalids() ) {
          				// Hide error containers on last error
          				this.toHide = this.toHide.add( this.containers );
          			}
          			this.showErrors();
          			return result;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
          		showErrors: function(errors) {
          			if(errors) {
          				// add items to error list and map
          				$.extend( this.errorMap, errors );
          				this.errorList = [];
          				for ( var name in errors ) {
          					this.errorList.push({
          						message: errors[name],
          						element: this.findByName(name)[0]
          					});
          				}
          				// remove items from success list
          				this.successList = $.grep( this.successList, function(element) {
          					return !(element.name in errors);
          				});
          			}
          			this.settings.showErrors
          				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
          				: this.defaultShowErrors();
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
          		resetForm: function() {
          			if ( $.fn.resetForm )
          				$( this.currentForm ).resetForm();
          			this.submitted = {};
          			this.prepareForm();
          			this.hideErrors();
          			this.elements().removeClass( this.settings.errorClass );
          		},
          		
          		numberOfInvalids: function() {
          			return this.objectLength(this.invalid);
          		},
          		
          		objectLength: function( obj ) {
          			var count = 0;
          			for ( var i in obj )
          				count++;
          			return count;
          		},
          		
          		hideErrors: function() {
          			this.addWrapper( this.toHide ).hide();
          		},
          		
          		valid: function() {
          			return this.size() == 0;
          		},
          		
          		size: function() {
          			return this.errorList.length;
          		},
          		
          		focusInvalid: function() {
          			if( this.settings.focusInvalid ) {
          				try {
          					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
          					.filter(":visible")
          					.focus()
          					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
          					.trigger("focusin");
          				} catch(e) {
          					// ignore IE throwing errors when focusing hidden elements
          				}
          			}
          		},
          		
          		findLastActive: function() {
          			var lastActive = this.lastActive;
          			return lastActive && $.grep(this.errorList, function(n) {
          				return n.element.name == lastActive.name;
          			}).length == 1 && lastActive;
          		},
          		
          		elements: function() {
          			var validator = this,
          				rulesCache = {};
          			
          			// select all valid inputs inside the form (no submit or reset buttons)
          			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
          			return $([]).add(this.currentForm.elements)
          			.filter(":input")
          			.not(":submit, :reset, :image, [disabled]")
          			.not( this.settings.ignore )
          			.filter(function() {
          				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
          			
          				// select only the first element for each name, and only those with rules specified
          				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
          					return false;
          				
          				rulesCache[this.name] = true;
          				return true;
          			});
          		},
          		
          		clean: function( selector ) {
          			return $( selector )[0];
          		},
          		
          		errors: function() {
          			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
          		},
          		
          		reset: function() {
          			this.successList = [];
          			this.errorList = [];
          			this.errorMap = {};
          			this.toShow = $([]);
          			this.toHide = $([]);
          			this.currentElements = $([]);
          		},
          		
          		prepareForm: function() {
          			this.reset();
          			this.toHide = this.errors().add( this.containers );
          		},
          		
          		prepareElement: function( element ) {
          			this.reset();
          			this.toHide = this.errorsFor(element);
          		},
          	
          		check: function( element ) {
          			element = this.clean( element );
          			
          			// if radio/checkbox, validate first element in group instead
          			if (this.checkable(element)) {
          				element = this.findByName( element.name )[0];
          			}
          			
          			var rules = $(element).rules();
          			var dependencyMismatch = false;
          			for( method in rules ) {
          				var rule = { method: method, parameters: rules[method] };
          				try {
          					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
          					
          					// if a method indicates that the field is optional and therefore valid,
          					// don't mark it as valid when there are no other rules
          					if ( result == "dependency-mismatch" ) {
          						dependencyMismatch = true;
          						continue;
          					}
          					dependencyMismatch = false;
          					
          					if ( result == "pending" ) {
          						this.toHide = this.toHide.not( this.errorsFor(element) );
          						return;
          					}
          					
          					if( !result ) {
          						this.formatAndAdd( element, rule );
          						return false;
          					}
          				} catch(e) {
          					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
          						 + ", check the '" + rule.method + "' method", e);
          					throw e;
          				}
          			}
          			if (dependencyMismatch)
          				return;
          			if ( this.objectLength(rules) )
          				this.successList.push(element);
          			return true;
          		},
          		
          		// return the custom message for the given element and validation method
          		// specified in the element's "messages" metadata
          		customMetaMessage: function(element, method) {
          			if (!$.metadata)
          				return;
          			
          			var meta = this.settings.meta
          				? $(element).metadata()[this.settings.meta]
          				: $(element).metadata();
          			
          			return meta && meta.messages && meta.messages[method];
          		},
          		
          		// return the custom message for the given element name and validation method
          		customMessage: function( name, method ) {
          			var m = this.settings.messages[name];
          			return m && (m.constructor == String
          				? m
          				: m[method]);
          		},
          		
          		// return the first defined argument, allowing empty strings
          		findDefined: function() {
          			for(var i = 0; i < arguments.length; i++) {
          				if (arguments[i] !== undefined)
          					return arguments[i];
          			}
          			return undefined;
          		},
          		
          		defaultMessage: function( element, method) {
          			return this.findDefined(
          				this.customMessage( element.name, method ),
          				this.customMetaMessage( element, method ),
          				// title is never undefined, so handle empty string as undefined
          				!this.settings.ignoreTitle && element.title || undefined,
          				$.validator.messages[method],
          				"<strong>Warning: No message defined for " + element.name + "</strong>"
          			);
          		},
          		
          		formatAndAdd: function( element, rule ) {
          			var message = this.defaultMessage( element, rule.method ),
          				theregex = /\$?\{(\d+)\}/g;
          			if ( typeof message == "function" ) {
          				message = message.call(this, rule.parameters, element);
          			} else if (theregex.test(message)) {
          				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
          			}			
          			this.errorList.push({
          				message: message,
          				element: element
          			});
          			
          			this.errorMap[element.name] = message;
          			this.submitted[element.name] = message;
          		},
          		
          		addWrapper: function(toToggle) {
          			if ( this.settings.wrapper )
          				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
          			return toToggle;
          		},
          		
          		defaultShowErrors: function() {
          			for ( var i = 0; this.errorList[i]; i++ ) {
          				var error = this.errorList[i];
          				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
          				this.showLabel( error.element, error.message );
          			}
          			if( this.errorList.length ) {
          				this.toShow = this.toShow.add( this.containers );
          			}
          			if (this.settings.success) {
          				for ( var i = 0; this.successList[i]; i++ ) {
          					this.showLabel( this.successList[i] );
          				}
          			}
          			if (this.settings.unhighlight) {
          				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
          					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
          				}
          			}
          			this.toHide = this.toHide.not( this.toShow );
          			this.hideErrors();
          			this.addWrapper( this.toShow ).show();
          		},
          		
          		validElements: function() {
          			return this.currentElements.not(this.invalidElements());
          		},
          		
          		invalidElements: function() {
          			return $(this.errorList).map(function() {
          				return this.element;
          			});
          		},
          		
          		showLabel: function(element, message) {
          			var label = this.errorsFor( element );
          			if ( label.length ) {
          				// refresh error/success class
          				label.removeClass().addClass( this.settings.errorClass );
          			
          				// check if we have a generated label, replace the message then
          				label.attr("generated") && label.html(message);
          			} else {
          				// create label
          				label = $("<" + this.settings.errorElement + "/>")
          					.attr({"for":  this.idOrName(element), generated: true})
          					.addClass(this.settings.errorClass)
          					.html(message || "");
          				if ( this.settings.wrapper ) {
          					// make sure the element is visible, even in IE
          					// actually showing the wrapped element is handled elsewhere
          					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
          				}
          				if ( !this.labelContainer.append(label).length )
          					this.settings.errorPlacement
          						? this.settings.errorPlacement(label, $(element) )
          						: label.insertAfter(element);
          			}
          			if ( !message && this.settings.success ) {
          				label.text("");
          				typeof this.settings.success == "string"
          					? label.addClass( this.settings.success )
          					: this.settings.success( label );
          			}
          			this.toShow = this.toShow.add(label);
          		},
          		
          		errorsFor: function(element) {
          			var name = this.idOrName(element);
              		return this.errors().filter(function() {
          				return $(this).attr('for') == name;
          			});
          		},
          		
          		idOrName: function(element) {
          			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
          		},
          
          		checkable: function( element ) {
          			return /radio|checkbox/i.test(element.type);
          		},
          		
          		findByName: function( name ) {
          			// select by name and filter by form for performance over form.find("[name=...]")
          			var form = this.currentForm;
          			return $(document.getElementsByName(name)).map(function(index, element) {
          				return element.form == form && element.name == name && element  || null;
          			});
          		},
          		
          		getLength: function(value, element) {
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				return $("option:selected", element).length;
          			case 'input':
          				if( this.checkable( element) )
          					return this.findByName(element.name).filter(':checked').length;
          			}
          			return value.length;
          		},
          	
          		depend: function(param, element) {
          			return this.dependTypes[typeof param]
          				? this.dependTypes[typeof param](param, element)
          				: true;
          		},
          	
          		dependTypes: {
          			"boolean": function(param, element) {
          				return param;
          			},
          			"string": function(param, element) {
          				return !!$(param, element.form).length;
          			},
          			"function": function(param, element) {
          				return param(element);
          			}
          		},
          		
          		optional: function(element) {
          			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
          		},
          		
          		startRequest: function(element) {
          			if (!this.pending[element.name]) {
          				this.pendingRequest++;
          				this.pending[element.name] = true;
          			}
          		},
          		
          		stopRequest: function(element, valid) {
          			this.pendingRequest--;
          			// sometimes synchronization fails, make sure pendingRequest is never < 0
          			if (this.pendingRequest < 0)
          				this.pendingRequest = 0;
          			delete this.pending[element.name];
          			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
          				$(this.currentForm).submit();
          				this.formSubmitted = false;
          			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          				this.formSubmitted = false;
          			}
          		},
          		
          		previousValue: function(element) {
          			return $.data(element, "previousValue") || $.data(element, "previousValue", {
          				old: null,
          				valid: true,
          				message: this.defaultMessage( element, "remote" )
          			});
          		}
          		
          	},
          	
          	classRuleSettings: {
          		required: {required: true},
          		email: {email: true},
          		url: {url: true},
          		date: {date: true},
          		dateISO: {dateISO: true},
          		dateDE: {dateDE: true},
          		number: {number: true},
          		numberDE: {numberDE: true},
          		digits: {digits: true},
          		creditcard: {creditcard: true}
          	},
          	
          	addClassRules: function(className, rules) {
          		className.constructor == String ?
          			this.classRuleSettings[className] = rules :
          			$.extend(this.classRuleSettings, className);
          	},
          	
          	classRules: function(element) {
          		var rules = {};
          		var classes = $(element).attr('class');
          		classes && $.each(classes.split(' '), function() {
          			if (this in $.validator.classRuleSettings) {
          				$.extend(rules, $.validator.classRuleSettings[this]);
          			}
          		});
          		return rules;
          	},
          	
          	attributeRules: function(element) {
          		var rules = {};
          		var $element = $(element);
          		
          		for (method in $.validator.methods) {
          			var value = $element.attr(method);
          			if (value) {
          				rules[method] = value;
          			}
          		}
          		
          		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
          		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
          			delete rules.maxlength;
          		}
          		
          		return rules;
          	},
          	
          	metadataRules: function(element) {
          		if (!$.metadata) return {};
          		
          		var meta = $.data(element.form, 'validator').settings.meta;
          		return meta ?
          			$(element).metadata()[meta] :
          			$(element).metadata();
          	},
          	
          	staticRules: function(element) {
          		var rules = {};
          		var validator = $.data(element.form, 'validator');
          		if (validator.settings.rules) {
          			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
          		}
          		return rules;
          	},
          	
          	normalizeRules: function(rules, element) {
          		// handle dependency check
          		$.each(rules, function(prop, val) {
          			// ignore rule when param is explicitly false, eg. required:false
          			if (val === false) {
          				delete rules[prop];
          				return;
          			}
          			if (val.param || val.depends) {
          				var keepRule = true;
          				switch (typeof val.depends) {
          					case "string":
          						keepRule = !!$(val.depends, element.form).length;
          						break;
          					case "function":
          						keepRule = val.depends.call(element, element);
          						break;
          				}
          				if (keepRule) {
          					rules[prop] = val.param !== undefined ? val.param : true;
          				} else {
          					delete rules[prop];
          				}
          			}
          		});
          		
          		// evaluate parameters
          		$.each(rules, function(rule, parameter) {
          			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
          		});
          		
          		// clean number parameters
          		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
          			if (rules[this]) {
          				rules[this] = Number(rules[this]);
          			}
          		});
          		$.each(['rangelength', 'range'], function() {
          			if (rules[this]) {
          				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
          			}
          		});
          		
          		if ($.validator.autoCreateRanges) {
          			// auto-create ranges
          			if (rules.min && rules.max) {
          				rules.range = [rules.min, rules.max];
          				delete rules.min;
          				delete rules.max;
          			}
          			if (rules.minlength && rules.maxlength) {
          				rules.rangelength = [rules.minlength, rules.maxlength];
          				delete rules.minlength;
          				delete rules.maxlength;
          			}
          		}
          		
          		// To support custom messages in metadata ignore rule methods titled "messages"
          		if (rules.messages) {
          			delete rules.messages;
          		}
          		
          		return rules;
          	},
          	
          	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
          	normalizeRule: function(data) {
          		if( typeof data == "string" ) {
          			var transformed = {};
          			$.each(data.split(/\s/), function() {
          				transformed[this] = true;
          			});
          			data = transformed;
          		}
          		return data;
          	},
          	
          	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
          	addMethod: function(name, method, message) {
          		$.validator.methods[name] = method;
          		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
          		if (method.length < 3) {
          			$.validator.addClassRules(name, $.validator.normalizeRule(name));
          		}
          	},
          
          	methods: {
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/required
          		required: function(value, element, param) {
          			// check if dependency is met
          			if ( !this.depend(param, element) )
          				return "dependency-mismatch";
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				// could be an array for select-multiple or a string, both are fine this way
          				var val = $(element).val();
          				return val && val.length > 0;
          			case 'input':
          				if ( this.checkable(element) )
          					return this.getLength(value, element) > 0;
          			default:
          				return $.trim(value).length > 0;
          			}
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/remote
          		remote: function(value, element, param) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			
          			var previous = this.previousValue(element);
          			if (!this.settings.messages[element.name] )
          				this.settings.messages[element.name] = {};
          			previous.originalMessage = this.settings.messages[element.name].remote;
          			this.settings.messages[element.name].remote = previous.message;
          			
          			param = typeof param == "string" && {url:param} || param; 
          			
          			if ( previous.old !== value ) {
          				previous.old = value;
          				var validator = this;
          				this.startRequest(element);
          				var data = {};
          				data[element.name] = value;
          				$.ajax($.extend(true, {
          					url: param,
          					mode: "abort",
          					port: "validate" + element.name,
          					dataType: "json",
          					data: data,
          					success: function(response) {
          						validator.settings.messages[element.name].remote = previous.originalMessage;
          						var valid = response === true;
          						if ( valid ) {
          							var submitted = validator.formSubmitted;
          							validator.prepareElement(element);
          							validator.formSubmitted = submitted;
          							validator.successList.push(element);
          							validator.showErrors();
          						} else {
          							var errors = {};
          							var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
          							errors[element.name] = $.isFunction(message) ? message(value) : message;
          							validator.showErrors(errors);
          						}
          						previous.valid = valid;
          						validator.stopRequest(element, valid);
          					}
          				}, param));
          				return "pending";
          			} else if( this.pending[element.name] ) {
          				return "pending";
          			}
          			return previous.valid;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
          		minlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
          		maxlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
          		rangelength: function(value, element, param) {
          			var length = this.getLength($.trim(value), element);
          			return this.optional(element) || ( length >= param[0] && length <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/min
          		min: function( value, element, param ) {
          			return this.optional(element) || value >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/max
          		max: function( value, element, param ) {
          			return this.optional(element) || value <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/range
          		range: function( value, element, param ) {
          			return this.optional(element) || ( value >= param[0] && value <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/email
          		email: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
          			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/url
          		url: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
          			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
          		},
                  
          		// http://docs.jquery.com/Plugins/Validation/Methods/date
          		date: function(value, element) {
          			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
          		dateISO: function(value, element) {
          			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/number
          		number: function(value, element) {
          			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/digits
          		digits: function(value, element) {
          			return this.optional(element) || /^\d+$/.test(value);
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
          		// based on http://en.wikipedia.org/wiki/Luhn
          		creditcard: function(value, element) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			// accept only digits and dashes
          			if (/[^0-9-]+/.test(value))
          				return false;
          			var nCheck = 0,
          				nDigit = 0,
          				bEven = false;
          
          			value = value.replace(/\D/g, "");
          
          			for (var n = value.length - 1; n >= 0; n--) {
          				var cDigit = value.charAt(n);
          				var nDigit = parseInt(cDigit, 10);
          				if (bEven) {
          					if ((nDigit *= 2) > 9)
          						nDigit -= 9;
          				}
          				nCheck += nDigit;
          				bEven = !bEven;
          			}
          
          			return (nCheck % 10) == 0;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/accept
          		accept: function(value, element, param) {
          			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
          			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
          		equalTo: function(value, element, param) {
          			// bind to the blur event of the target in order to revalidate whenever the target field is updated
          			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
          			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
          				$(element).valid();
          			});
          			return value == target.val();
          		}
          		
          	}
          	
          });
          
          // deprecated, use $.validator.format instead
          $.format = $.validator.format;
          
          })(jQuery);
          
          // ajax mode: abort
          // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
          // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
          ;(function($) {
          	var ajax = $.ajax;
          	var pendingRequests = {};
          	$.ajax = function(settings) {
          		// create settings for compatibility with ajaxSetup
          		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
          		var port = settings.port;
          		if (settings.mode == "abort") {
          			if ( pendingRequests[port] ) {
          				pendingRequests[port].abort();
          			}
          			return (pendingRequests[port] = ajax.apply(this, arguments));
          		}
          		return ajax.apply(this, arguments);
          	};
          })(jQuery);
          
          // provides cross-browser focusin and focusout events
          // IE has native support, in other browsers, use event caputuring (neither bubbles)
          
          // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
          // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
          ;(function($) {
          	// only implement if not provided by jQuery core (since 1.4)
          	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
          	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
          		$.each({
          			focus: 'focusin',
          			blur: 'focusout'	
          		}, function( original, fix ){
          			$.event.special[fix] = {
          				setup:function() {
          					this.addEventListener( original, handler, true );
          				},
          				teardown:function() {
          					this.removeEventListener( original, handler, true );
          				},
          				handler: function(e) {
          					arguments[0] = $.event.fix(e);
          					arguments[0].type = fix;
          					return $.event.handle.apply(this, arguments);
          				}
          			};
          			function handler(e) {
          				e = $.event.fix(e);
          				e.type = fix;
          				return $.event.handle.call(this, e);
          			}
          		});
          	};
          	$.extend($.fn, {
          		validateDelegate: function(delegate, type, handler) {
          			return this.bind(type, function(event) {
          				var target = $(event.target);
          				if (target.is(delegate)) {
          					return handler.apply(target, arguments);
          				}
          			});
          		}
          	});
          })(jQuery);
          
          Evidence
          2147483647
          Solution

          Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

        5. GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js
          Alert tags
          Alert description

          A timestamp was disclosed by the application/web server - Unix

          Other info

          604800000, which evaluates to: 1989-03-01 19:00:00

          Request
          Request line and header section (369 bytes)
          GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 25809
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"25809-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (25809 bytes)
          /**
           * Version: 1.0 Alpha-1 
           * Build Date: 13-Nov-2007
           * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
           * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
           * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
           */
          Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
          Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
          return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
          if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
          var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
          if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
          if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
          if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
          if(x.month||x.months){this.addMonths(x.month||x.months);}
          if(x.year||x.years){this.addYears(x.year||x.years);}
          if(x.day||x.days){this.addDays(x.day||x.days);}
          return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
          return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
          if(!x.second&&x.second!==0){x.second=-1;}
          if(!x.minute&&x.minute!==0){x.minute=-1;}
          if(!x.hour&&x.hour!==0){x.hour=-1;}
          if(!x.day&&x.day!==0){x.day=-1;}
          if(!x.month&&x.month!==0){x.month=-1;}
          if(!x.year&&x.year!==0){x.year=-1;}
          if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
          if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
          if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
          if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
          if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
          if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
          if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
          if(x.timezone){this.setTimezone(x.timezone);}
          if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
          return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
          var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
          return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
          Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
          return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
          var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
          return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
          var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
          return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
          (function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
          break;}
          return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
          return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
          throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
          return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
          if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){r=null;}
          if(r){return r;}}
          throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
          return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
          rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
          s=q[1];}
          if(!r){throw new $P.Exception(s);}
          if(q){throw new $P.Exception(q[1]);}
          if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
          return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
          rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
          if(!last&&q[1].length===0){last=true;}
          if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
          p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
          if(rx[1].length<best[1].length){best=rx;}
          if(best[1].length===0){break;}}
          if(best[0].length===0){return best;}
          if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
          best[1]=q[1];}
          return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
          return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
          if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
          var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
          return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
          this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
          var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
          return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
          for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
          if(this.now){return new Date();}
          var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
          if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
          if(!this.unit){this.unit="day";}
          if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
          if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
          this[this.unit+"s"]=this.value*orient;}
          return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
          if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
          if(this.month&&!this.day){this.day=1;}
          return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
          fn=_C[keys]=_.any.apply(null,px);}
          return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
          return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
          return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
          try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
          
          Evidence
          604800000
          Solution

          Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

        6. GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js
          Alert tags
          Alert description

          A timestamp was disclosed by the application/web server - Unix

          Other info

          86400000, which evaluates to: 1972-09-26 20:00:00

          Request
          Request line and header section (369 bytes)
          GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 25809
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"25809-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (25809 bytes)
          /**
           * Version: 1.0 Alpha-1 
           * Build Date: 13-Nov-2007
           * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
           * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
           * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
           */
          Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
          Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
          return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
          if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
          var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
          if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
          if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
          if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
          if(x.month||x.months){this.addMonths(x.month||x.months);}
          if(x.year||x.years){this.addYears(x.year||x.years);}
          if(x.day||x.days){this.addDays(x.day||x.days);}
          return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
          return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
          if(!x.second&&x.second!==0){x.second=-1;}
          if(!x.minute&&x.minute!==0){x.minute=-1;}
          if(!x.hour&&x.hour!==0){x.hour=-1;}
          if(!x.day&&x.day!==0){x.day=-1;}
          if(!x.month&&x.month!==0){x.month=-1;}
          if(!x.year&&x.year!==0){x.year=-1;}
          if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
          if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
          if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
          if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
          if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
          if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
          if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
          if(x.timezone){this.setTimezone(x.timezone);}
          if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
          return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
          var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
          return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
          Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
          return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
          var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
          return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
          var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
          return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
          (function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
          break;}
          return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
          return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
          throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
          return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
          if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){r=null;}
          if(r){return r;}}
          throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
          return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
          rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
          s=q[1];}
          if(!r){throw new $P.Exception(s);}
          if(q){throw new $P.Exception(q[1]);}
          if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
          return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
          rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
          if(!last&&q[1].length===0){last=true;}
          if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
          p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
          if(rx[1].length<best[1].length){best=rx;}
          if(best[1].length===0){break;}}
          if(best[0].length===0){return best;}
          if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
          best[1]=q[1];}
          return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
          return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
          if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
          var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
          return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
          this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
          var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
          return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
          for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
          if(this.now){return new Date();}
          var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
          if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
          if(!this.unit){this.unit="day";}
          if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
          if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
          this[this.unit+"s"]=this.value*orient;}
          return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
          if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
          if(this.month&&!this.day){this.day=1;}
          return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
          fn=_C[keys]=_.any.apply(null,px);}
          return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
          return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
          return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
          try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
          
          Evidence
          86400000
          Solution

          Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

        7. GET https://dev.duracloud.org/duradmin/style/base.css
          Alert tags
          Alert description

          A timestamp was disclosed by the application/web server - Unix

          Other info

          20080212, which evaluates to: 1970-08-21 05:50:12

          Request
          Request line and header section (362 bytes)
          GET https://dev.duracloud.org/duradmin/style/base.css HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (437 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/css
          Content-Length: 21115
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"21115-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (21115 bytes)
          /*
          * Created by Daniel Bernstein
          * Modified by Charles Hacskaylo
          */
          
          /* RESETTERS *************************************************/
          /* Eric Meyer:
          /* v1.0 | 20080212 */
          
          html, body, div, span, applet, object, iframe,
          h1, h2, h3, h4, h5, h6, p, blockquote, pre,
          a, abbr, acronym, address, big, button, cite, code,
          del, dfn, em, font, img, ins, kbd, q, s, samp,
          small, strike, strong, sub, sup, tt, var,
          b, u, i, center,
          dl, dt, dd, ol, ul, li,
          fieldset, form, label, legend,
          table, caption, tbody, tfoot, thead, tr, th, td {
          	margin: 0;
          	padding: 0;
          	border: 0;
          	outline: 0;
          	font-size: 100%;
          	vertical-align: baseline;
          	background: transparent;
          }
          body {
          	line-height: 1;
          }
          
          a:hover {
            cursor:pointer;
          }
          
          ol, ul {
          	list-style: none;
          }
          
          
          ul.bullets,
          #static-panel ul
          {
          	line-height:130%;
          	list-style:square;
          	margin-left:15px;
          }
          
          blockquote, q {
          	quotes: none;
          }
          blockquote:before, blockquote:after,
          q:before, q:after {
          	content: '';
          	content: none;
          }
          
          /* remember to define focus styles! */
          :focus {
          	outline: 0;
          }
          
          /* tables still need 'cellspacing="0"' in the markup */
          table {
          	border-collapse: collapse;
          	border-spacing: 0;
          }
          
          /* set input color for autofill */
          input:-webkit-autofill {
              color: #000 !important;
          }
          
          
          
          
          
          
          /* CLEARFIX *************************************************/
          
          .clearfix:after {
               visibility: hidden;
               display: block;
               font-size: 0;
               content: " ";
               clear: both;
               height: 0;
               }
          .clearfix { display: inline-block; }
          /* start commented backslash hack \*/
          * html .clearfix { height: 1%; }
          .clearfix { display: block; }
          /* close commented backslash hack */
          
          
          .horizontal-list li
          {
          	display:inline-block;
          }
          
          
          body {
          	background:#fff url(../images/bg_clouds.jpg) repeat-y;
          	font-family: Verdana, Helvetica, sans-serif;
          	font-size:1em;
          	*font-size:	90%; /* IE only */
          	margin-right:10px !important;
          }
          
          h1, h2, h3
          {
          	font-family:Helvetica, Sans-Serif;
          }
          
          h1 { font-size:2em; font-weight:normal; }
          h2 { font-size:1.3em; font-weight:normal; }
          h3 { font-size:1em; }
          
          
          .float-l {float:left; margin-left:0; }
          .float-r {float:right; margin-right:0; }
          .content-centered { text-align:center !important; }
          
          
          /* MAIN PAGE ELEMENTS ******************************************/
          
          body > #page-header
          {
          	height:87px;
          	min-width:960px;
          	padding-top:10px;
          }
          
          .pane-L1-body
          {
          	background:url(../images/bg_L1.png) no-repeat top right;
          	padding-top:5px;
          }
          
          .pane-L1-body a
          {
          	color:#ccc;
          }
          
          .center-pane-north
          {
          	color:#9b9b9b;
          	font-size:13px;
          	padding:5px 10px;
          	z-index:4 !important; /* needed to list spaces provider menu above elements below it */
          }
          
          .dc-prototype {
          
          	display:none;
          }
          
          .list-browser
          {
          	background:#4F4F4F no-repeat top right;
          }
          
          .ui-layout-pane-west
          {
          	font-size:11px;
          }
          
          .dc-item-list-filter
          {
          	background-color:#4F4F4F;
          	border:1px solid #999;
          	color:#ccc;
          	font-style:italic;
          	padding:2px;
          	width:143px;
          	float: right;
          }
          
          .dc-item-list-wrapper
          {
          	background-color:#cbcbcb;
          	border:1px solid #595959;
          	border-top-color:#333;
          	border-bottom-color:#4F4F4F;
          	color:#000;
          	min-width:250px !important;
          	overflow:auto;
          	width:auto !important;
          }
          
          .dc-item-list-wrapper a
          {
          	color:#000;
          }
          
          .dc-selectablelist-footer {
          	padding-right:10px;
          }
          
          .dc-link:hover {
          	text-decoration:underline;
          	cursor: pointer;
          }
          
          .dc-link:after {
          	content:'>';
          }
          
          .dc-selectablelist-hl {
          	background:#DDDDDD;
          }
          
          
          .list-header
          {
          	padding:5px 5px 5px 10px;
          }
          
          .header-section
          {
          	min-width:250px !important;
          	padding-bottom:3px;
          	white-space:nowrap;
          }
          
          .list-header h2
          {
          	display:inline-block;
          	font-size:16px;
          	line-height:24px;
          }
          
          #spaces-list-view .list-header .button span,
          #content-item-list-view .list-header .button span
          {
          	width:130px;
          }
          
          #space-filter {
              width: 100px;
          }
          
          .item-scroll-action:hover {
          	color:#EEE;
          	font-weight:bold;
          }
          
          .item-scroll-action{
          	text-decoration: none;
          }
          
          .ui-layout-pane
          {
          	color:#fff;
          }
          
          #provider-logo
          {
              float:left;
              margin-left:0;
              height:39px;
          	width:184px;
          }
          
          .amazon_s3-logo
          {
              background:url(../images/amazon.png) no-repeat;
          }
          
          .amazon_glacier-logo
          {
              background:url(../images/amazon.png) no-repeat;
          }
          
          .chronopolis-logo
          {
          	background:url(../images/chronopolis.png) no-repeat;
          }
          
          .swift_s3-logo
          {
              background:url(../images/swift.png) no-repeat;
          }
          
          .ui-layout-resizer
          {
          	background-color:#4b4b4b;
          	cursor:col-resize !important;
          }
          
          .ui-layout-resizer:hover
          {
          	background-color:#257bba !important;
          	cursor:col-resize !important;
          	opacity:1 !important;
          }
          
          #spaces-list-view-resizer
          {
          	background-color:#4F4F4F;
          }
          
          #list-browser-resizer
          {
          
          }
          
          ul.dc-user-config > li:first-child, .dc-exclusion-group > ul > li {
          	border-top:0px;
          }
          
          ul.dc-user-config > li:last-child {
          	border-bottom: 0px;
          }
          
          
          .dc-exclusion-group  li {
          	margin-left: 30px;
          	border-bottom: 0px;
          	border-top: 0px;
          }
          
          .dc-exclusion-group  ul {
          	margin-left:30px;
          	border-left:1px solid #555555;
          	background: #666666 !important;
          	padding-left:10px;
          }
          
          .dc-exclusion-group > ul > li > label {
          	width:250px !important;
          	margin-right:10px;
          }
          
          .dc-exclusion-group > ul > li {
          	border-bottom: 1px solid #777777;
          }
          
          .dc-exclusion-group > label, .dc-exclusion-group > select
          {
          	margin-bottom: 10px;
          }
          
          .dc-exclusion-group  li:last-child {
          	border-bottom: 0px;
          }
          
          
          .ui-layout-toggler
          {
          	background:url(../images/grippy.gif) no-repeat left top;
          	height:100px !important;
          }
          
          .footer
          {
          	background:url(../images/bg_L1_btm.png) no-repeat right -8px;
          	height:70px !important;
          	padding:0px 10px;
          }
          
          .footer #status-holder
          {
          	color:#ccc;
          	font-size:11px;
          	height:27px;
          	padding-top:2px;
          	text-align:right;
          }
          
          .footer #status-holder a { color:#ccc; text-decoration:none; }
          .footer #status-holder a:hover { color:#fff; }
          
          #status-holder #progress-bar
          {
          	background:url("/duradmin/images/loading-bar-green.gif") no-repeat left 2px;
          	display:inline-block;
          	height:20px;
          	width:110px;
          	vertical-align:middle;
          
          }
          
          #status-holder {
          }
          
          #footer-content { margin-top:15px; }
          
          #footer-content #logo-ds
          {
          	background:url(../images/logo_lyrasis.png) no-repeat top left;
          	margin-top:-5px;
          	width:116px;
          	height:18px;
          }
          
          .footer .sep
          {
          	color:#272727;
          }
          
          .hint
          {
          	font-size:11px;
          }
          
          /* TABS **********************************************/
          /* Extends css.flex *****/
          
          .dc-main-tabs
          {
          	position:absolute;
          	left:10px;
          	top:65px;
          	opacity:0.7;
          }
          
          .dc-main-tabs li
          {
          	margin:0;
          }
          
          .dc-main-tabs a,
          .dc-main-tabs a span
          {
          	color:#000;
          	font-size:13px;
          	height:22px;
          	line-height:22px;
          }
          
          .dc-main-tabs a span
          {
          	margin:0 -2px;
          	padding-left:2px;
          	font-weight:bold;
          }
          
          .dc-main-tabs .selected a,
          .dc-main-tabs a:hover
          {
          	background:url(../images/tab.gif) no-repeat top left;
          }
          
          .dc-main-tabs .selected a span,
          .dc-main-tabs a:hover span
          {
          	background:url(../images/tab.gif) no-repeat top right;
          	color:#fff !important;
          }
          
          /* LIST AND ITEMS **********************************************/
          
          .dc-item-list
          {
          	margin:5px;
          }
          
          .dc-item-list table
          {
          	width:100%;
          }
          
          .dc-item,
          .dc-item td,
          .dc-item-list th
          {
          	border-bottom:1px solid #bbbbbb;
          	border-collapse:  collapse;
          	color:#000;
          	padding-bottom:2px;
          	padding-top:2px;
          	text-align:left;
          	vertical-align:middle;
          }
          
          .dc-item {
              position:relative;
          	min-height:20px;
          }
          .dc-item-list td,
          .dc-item-list th
          {
          	padding:3px 5px;
          }
          
          .dc-item-list td.icon
          {
          	width:38px;
          }
          
          .dc-item-list th
          {
          	background-color:#aaa;
          	border-left:1px solid #ccc;
          }
          
          .dc-item-list td.icon div
          {
          	/* graphics format: art is 32 x 32, horizontal, with 10px between each, so total offset from icon to icon is 42px */
          	background:url(../images/icons_services.png) no-repeat;
          	width:32px;
          	height:32px;
          }
          
          /* replicate 0; general-compute -42; bit-integrity -84; image -126; video -168; file-transform -210; */
          
          .dc-item-list .service-replicate td.icon div { background-position:0 0; }
          .dc-item-list .service-generalcompute td.icon div { background-position:-42px 0; }
          .dc-item-list .service-bitintegrity td.icon div { background-position:-84px 0; }
          .dc-item-list .service-image td.icon div { background-position:-126px 0; }
          .dc-item-list .service-video td.icon div { background-position:-168px 0; }
          .dc-item-list .service-filetransform td.icon div { background-position:-210px 0; }
          
          /* bitintegrity */
          .dc-item-list .service-0 td.icon div { background-position:-84px 0; }
          .dc-item-list .service-1 td.icon div { background-position:-84px 0; }
          .dc-item-list .service-2 td.icon div { background-position:-84px 0; }
          
          /* image */
          .dc-item-list .service-5 td.icon div { background-position:-126px 0; }
          .dc-item-list .service-6 td.icon div { background-position:-126px 0; }
          .dc-item-list .service-7 td.icon div { background-position:-126px 0; }
          
          /* filetransform */
          .dc-item-list .service-8 td.icon div { background-position:-210px 0; }
          
          .dc-selected-list-item {
          	background-color:#7e7e7e;
          }
          
          input.dc-check-all
          {
          	margin-left:3px !important;
          }
          
          .dc-checked-selected-list-item {
          	background-color:#888;
          	color:#FFF;
          }
          
          .dc-checked-list-item {
          	background-color:#999;
          	color:#FFF;
          }
          
          .dc-item div:first-child {
          	/*
          
          	float:left;*/
          }
          
          .dc-item-list .dc-action-panel{
              position:absolute;
              right:0;
              top:4px;
          }
          
          .dc-action-panel
          {
          	/*margin-right:20px;*/
          }
          
          .dc-item-content {
              padding-right: 30px;
          }
          
          .dc-item .cb-holder{
          	padding:8px 8px 8px 5px;
          }
          
          .dc-item:hover,
          .dc-item:hover td
          {
          	background-color:#9b9b9b;
          	cursor: pointer;
          }
          
          /* PAGE TOP ********************************************************/
          
          #dc-logo-panel
          {
          	padding-left:10px;
          }
          
          #dc-logo,
          #dc-app-title
          {
          	background-repeat:no-repeat;
          	display:inline-block;
          	float:left;
          	height:45px;
          }
          
          #dc-logo
          {
          	background-image:url(../images/logo_top_duracloud.png);
          	width:110px;
          	color: transparent;
          }
          
          #page-header #dc-app-title
          {
          	width:280px;
          }
          
          #page-header #dc-user
          {
          	border-right:solid 1px #ccc;
          	height:60px;
          	margin-right:10px;
          	padding-right:20px;
          	text-align:right;
          	width:400px;
          }
          
          .outer,
          .outer a
          {
          	color:#2c2c2c;
          	font-size:14px;
          }
          
          .outer .icon-link:hover
          {
          	color:#000;
          }
          
          
          .dc-mouse-panel {
          	visibility: hidden;
          }
          
          .dc-mouse-panel-activator
          {
          	cursor:pointer;
          }
          
          .dc-toggler {
          	float:right;
          	background: url(../images/icon_sm_arw_blue_updown.gif) no-repeat right top;
          	width:11px;
          	height:25px;
          }
          
          .dc-toggler-close { background-position:left top; }
          
          
          .dc-expandable-panel div:first-child{
          	cursor: pointer;
          }
          
          /* DETAIL PANE ****************************************************/
          
          .detail-pane
          {
          	padding-right:5px !important;
          }
          
          .detail-pane h1
          {
          	color:#777;
          	margin-bottom:10px;
          }
          
          .detail-pane > .north {
          	overflow: auto;
          	overflow-x: auto;
          }
          
          .detail-pane th {
          	text-align: left;
          	background-color: #555;
          	padding: 5px 0px 5px 0px;
          }
          
          h2,.footer-prompt
          {
              color:#F0F0F0;
          }
          
          .footer-prompt {
            font-size: smaller;
          }
          
          .detail-pane h3
          {
          	color:#fff;
          	margin-bottom:10px;
          }
          
          .detail-pane .north
          {
          	background:url(../images/bg_details_header.png) repeat-x bottom left;
          	padding:0 10px;
          	position:relative;
          }
          
          .detail-pane .center
          {
          	background-color:#414141;
          	border:1px solid #2d2d2d;
          	border-top-color:#333;
          	border-bottom-color:#999;
          	font-family:Verdana, Sans-Serif;
          	font-size:11px;
          	overflow-x:hidden;
          	overflow-y:scroll;
          }
          
          .detail-pane .center {
          	width:auto !important;
          }
          
          .detail-pane .segment-header,
          #add-remove-properties-dialog .segment-header
          {
          	background:url(../images/bg_segment_header.gif) repeat-x top left;
          	border-bottom:1px solid #333;
          	color:#DBDBDB;
          	cursor:pointer;
          	font-size:13px;
          	height:28px;
          	line-height:25px;
          	padding:0 10px;
          }
          
          .detail-pane .segment-header:hover,
          #add-remove-properties-dialog .segment-header:hover
          {
          	color:#fff;
          }
          
          .detail-pane .segment-content,
          #add-remove-properties-dialog .segment-content
          {
          	padding:10px;
          }
          
          .detail-pane .segment-content table,
          #add-remove-properties-dialog .segment-content table
          {
          	width:100%;
          }
          
          .detail-pane .segment-content table td,
          #add-remove-properties-dialog .segment-content table td
          {
          	border-bottom:1px solid #555;
          	padding:4px 5px 4px 0;
          }
          
          .detail-pane .segment-content table td.label,
          span.label,
          #add-remove-properties-dialog .segment-content table td.label
          {
          	color:#999;
          }
          
          .detail-pane .segment-content table td.label,
          #add-remove-properties-dialog .segment-content table td.label
          {
          	width:30%;
          }
          
          
          .detail-pane .segment-content table td.value,
          #add-remove-properties-dialog .segment-content table td.value
          {
          	width:70%;
          }
          
          .detail-pane .segment-content input,
          #add-remove-properties-dialog .segment-content input
          {
          	background-color:#484747;
          	border:1px solid #727576;
          	color:#ccc;
          	padding:2px;
          }
          
          .segment-content h4 {
          	margin: 10px 0px 5px 0px;
          	padding: 10px 5px 10px 5px;
          	height: 25px;
          	border-top: 1px solid #555;
          }
          
          .segment-content h4 span {
          	margin-top: 5px;
          }
          .segment-content h4 button {
          	float:right;
          }
          
          
          .detail-pane .mime-type
          {
          	font-size:13px;
          	height:40px;
          	line-height:40px;
          	margin:10px 0;
          }
          
          .mime-type-image-holder
          {
          	background:url(../images/icons_mimetypes.png) no-repeat;
          	background-position:-40px 0;
          	height:40px;
          	width:40px;
          }
          
          .detail-pane .mime-type-image-holder
          {
          	margin-right:10px;
          }
          
          .mime-type-application { background-position:-80px 0 !important; }
          .mime-type-audio { background-position:-240px 0 !important; }
          .mime-type-compression { background-position:-480px 0 !important; }
          .mime-type-drawing { background-position:-200px 0 !important; }
          .mime-type-generic { background-position:0 0 !important; }
          .mime-type-globe { background-position:-160px 0 !important; }
          .mime-type-image { background-position:-200px 0 !important; }
          .mime-type-message { background-position:-280px 0 !important; }
          .mime-type-text { background-position:-320px 0 !important; }
          .mime-type-music { background-position:-360px 0 !important; }
          .mime-type-spreadsheet { background-position:-440px 0 !important; }
          .mime-type-unknown { background-position:-40px 0 !important; }
          .mime-type-xml { background-position:-520px 0 !important; }
          .mime-type-video { background-position:-120px 0 !important; }
          
          .preview-image-wrapper
          {
          	display:block;
          	margin:0 auto;
          	overflow:hidden;
          	text-align:center;
          	padding-top:10px;
          	padding-bottom:10px;
          	min-width:300px;
          	min-height:200px;
          }
          
          
          
           /* ERRORS *********************************************************/
          
           .error, .warning
           {
           	color:#ccc;
           	margin-bottom:10px;
           }
          
          .error,.failure
           {
           	border:1px solid #aa0000;
           	background-color:#990000;
           }
          .warning
           {
           	border:1px solid #ff9933;
          	background-color:#ff6600;
           }
          
           .success {
           	border:1px solid #00AA00;
          	background-color:#009900;
           }
          
           .info {
              background-color:#2e9acc;
           }
           .info, .success, .warning, .error {
          	border-radius: 5px;
          	padding:5px;
           }
          
          .detail-pane label.error {
          	padding:0px;
           }
          
           .health-check {
           	padding:5px;
           }
          
           /* MISC **********************************************************/
          
           .object-id {
           	display:none;
           }
          
           /*flyout select default styling ******************************************/
          
          .provider-widget
          {
          	display:inline-block;
          	position:relative;
          }
          
          .provider-widget ul
          {
          	-moz-border-radius:3px;
          	border-radius:3px;
          	-webkit-border-radius:3px;
          	background-color:#2886c0;
          	border:1px solid #257ab9;
          	border-bottom-color:#0c293f;
          	border-top-color:#2e9acc;
          	display:none;
          	padding:10px;
          	opacity:0.95;
          	position:absolute;
          	z-index:5000;
          }
          
          .provider-widget li
          {
          	border-top:1px solid #2e9acc;
          	white-space:nowrap;
          	min-width:100px;
          }
          
          .provider-widget li a
          {
          	color:#ffffff;
          	cursor:pointer;
          	display:block;
          	font-size:11px;
          	padding:6px 3px;
          	text-decoration:none;
          }
          
          .provider-widget li a:hover
          {
          	background-color:#2e9acc;
          	color:#fff;
          }
          
          /* doing this via jquery to support IE, so turned off here
          #select-provider-wrapper:hover ul
          {
          	display:block;
          }
          */
          
           .provider-widget li:first-child{
           	border-top:none !important;
           }
          
          .provider-widget > a,
          .provider-widget > a span
          {
          	background-image:url(../images/btn_provider.gif);
          
          }
          
          .provider-widget > a span i
          {
          	color:#76e8ff !important;
          	min-width:150px;
          }
          
          .provider-float
          {
              float: right;
          }
          
          .dc-expando-status {
          	height:20px;
          	width:30px;
          }
          
          .dc-busy {
          	background: url('../images/wait.gif') no-repeat center center;
          	display:inline-block; vertical-align:middle;
          	height:20px;
          	width:20px;
          }
          
          .dc-removing {
          	background-color: orange;
          	filter:alpha(opacity=0.25);
          	-moz-opacity:0.25;
          	-khtml-opacity: 0.25;
          	opacity: 0.25;
          }
          
          .dc-progressbar
          {
          	display:block;
          	background-color:#003300;
          	border:1px solid #000;
          	border-bottom-color:#454545;
          }
          
          .dc-progressbar .dc-progressbar-value
          {
          	background-color:#227722;
          	border:1px solid #228822;
          	border-top-color:#339933;
          	border-bottom-width:0;
          	color:#00cc00;
          	display:block;
          	overflow:visible;
          	padding:1px 0px 3px 0px;
          	text-align:left;
          	white-space:nowrap;
          }
          
          .dc-failure, .dc-progressbar .dc-failure {
          	background-color:#772222;
          	border:1px solid #882222;
          	border-top-color:#993333;
          	color:#cc0000;
          }
          
          .dc-cancelled, .dc-progress-bar .dc-cancelled {
          	background-color:#222277;
          	border:1px solid #222288;
          	border-top-color:#333399;
          	color:#0000cc;
          }
          
          
          .dc-progress-state {
          	padding-right:1em;
          }
          
          .dc-controls
          {
          	float:right;
          	color: white;
          }
          
          
          #busy-dialog-title {
          	margin-bottom:20px;
          }
          #busy-dialog-progressbar  {
          	height: 30px;
          	width: 100%;
          	background: url('../images/loading-bar-green.gif') no-repeat center center;
          }
          
          .ui-serviceconfig > div {
          	height: 420px;
          	overflow: auto;
          }
          
          
          p.ui-serviceconfig-no-config{
          	padding: 10px 0px 10px 0px;
          }
          
          /*
          * hiding the jquery-ui dialog title bars globally.
          */
          .ui-dialog-titlebar{
          	display:none;
          }
          
          
          .dc-graph {
          	width:300px;
          	height:150px;
          	padding:20px;
              margin-bottom:10px;
          }
          
          .dc-breadcrumb  li:after {
          	content:' :: '
          }
          
          
          .dc-breadcrumb li {
          	cursor: pointer;
          	font-size:0.9em;
          	color:#555
          }
          
          
          .dc-breadcrumb-title {
          	font-size:1.3em !important;
          	color:#555 !important;
          
          }
          
          
          .dc-breadcrumb ul{
          
          }
          
          .dc-report-panel {
          
          }
          
          .dc-hidden {
          	display:none;
          }
          .dc-date-slider > div {
          	 display:inline-block;
          }
          
          .number {
          	text-align:right;
          }
          
          
          
          
          table.tablesorter {
              background-color: #CDCDCD;
              font-family: arial;
              font-size: 8pt;
              margin: 10px 0 15px;
              text-align: left;
              width: 100%;
          }
          table.tablesorter thead tr th, table.tablesorter tfoot tr th {
              background-color: #E6EEEE;
              border: 1px solid #FFFFFF;
              font-size: 8pt;
              padding: 4px;
          }
          table.tablesorter thead tr .header {
              background-image: url("bg.gif");
              background-position: right center;
              background-repeat: no-repeat;
              cursor: pointer;
          }
          table.tablesorter tbody td {
              background-color: #FFFFFF;
              color: #3D3D3D;
              padding: 4px;
              vertical-align: top;
          }
          table.tablesorter tbody tr.odd td {
              background-color: #F0F0F6;
          }
          table.tablesorter thead tr .headerSortUp {
              background-image: url("../images/asc.gif");
          }
          table.tablesorter thead tr .headerSortDown {
              background-image: url("../images/desc.gif");
          }
          table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
              background-color: #8DBDD8;
          }
          
          table.tablesorter tr:nth-child(even) {
          	background-color: #DDDDDD;
          }
          
          table.tablesorter tr {
          	border-bottom: 1px solid #CCCCCC;
          }
          
          /*
          * Upload tool
          */
          
          .upload-tool {
          	padding:10px;
              position:relative;
          }
          
          .upload-tool-help {
              position:absolute;
              left:765px;
              font-size: 0.7em;
              margin-top: 4px;
          }
          
          .dc-controlpanel .dc-controlpanel-header > * {
          	float:right;
          }
          
          .dc-controlpanel .dc-controlpanel-header  {
          	background-color: #444;
          	padding: 5px;
          	height:25px;
          }
          
          .dc-controlpanel input[type="checkbox"]  {
          	margin:0px 5px 0px 5px !important;
          }
          
          table.dc-acls td:first-child {
          	width:50%;
          }
          
          table.dc-acls td:last-child {
          	width:25% ;
          }
          
          .user, .group {
          	padding-left:20px;
          }
          
          .dc-graph {
          	width:150px;
          	height:150px;
          	display:inline-block;
          }
          
          .dc-graph-holder {
          	display:inline-block;
          	text-align: center;
          }
          
          .dc-graph-holder {
          	margin-left: 40px;
          
          }
           .history-panel #summaries-graph {
           	height:150px;
          	display:inline-block;
          
           }
          
           .history-panel .segment-content > * {
              width: 95%;
           }
          
           .history-panel #summaries-legend {
          	display:block;
          	color: #EEE;
          	padding:5px;
           }
           .history-panel #summaries-legend table {
           	border: 1px solid #555;
           }
          
          .history-panel #summaries-legend .legendLabel{
          	color: #EEE;
          }
          
          .history-panel #summaries-legend table {
          	width: 50px !important;
          }
          
          .history-panel h6 {
          	margin-bottom: 10px;
          }
          
          #streaming-pane > p {
          	margin-bottom: 20px;
          }
          
          #hlsSwitchControl {
          	border-bottom: 1px solid #555;
          	padding-bottom:10px;
          	margin-bottom:10px;
          	width:100%;
          	display: inline-block;
          	margin-top: 20px;
          
          }
          
          #hlsSwitchControl {
          	margin-top: 25px;
          }
          
          .streaming-switch-holder {
          	height:20px;
          	display:inline-block;
          	white-space: nowrap;
          	margin-bottom: 20px;
          }
          .streaming-switch-holder label {
          	font-size: 1.25em;
          }
          
          .streaming-switch {
          	display:inline-block;
          	font-size:0.7em;
          }
          
          .button-bar {
          	white-space: nowrap;
          }
          
          .object-name {
          	white-space: nowrap;
          	margin-bottom: 10px !important;
          }
          
          button#enable-streaming {
          	margin-top:10px;
          }
          
          button.add-space-button {
            display: none;
          }
          
          .dc-item-divider {
            background-color:#5b5b5b;
            padding:5px;
            font-weight: bold;
          
          }
          
          .dc-busy-holder {
              background: url('../images/wait.gif') no-repeat left center;
              display:inline-block;
              vertical-align:middle;
              height:20px;
              width:20px;
              min-width:30px;
              font-size: 10px;
              padding-left:20px;
          }
          
          div.snapshot.dc-item {
            padding: 5px 5px 0px 7px;
          }
          Evidence
          20080212
          Solution

          Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

  4. Risk=Informational, Confidence=Low (37)

    1. https://dev.duracloud.org (37)

      1. Information Disclosure - Suspicious Comments (37)
        1. GET https://dev.duracloud.org
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSERNAME\b and was detected in the element starting with: "<script type="text/javascript">

          $(function() {

          $("#username").focus();

          $("#button-login").click(function(evt) {

          ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (239 bytes)
          GET https://dev.duracloud.org HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:52 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=5E31D0F4635FF98D07FB6B0F6D1FBCA9; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          username
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        2. GET https://dev.duracloud.org/duradmin/
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSERNAME\b and was detected in the element starting with: "<script type="text/javascript">

          $(function() {

          $("#username").focus();

          $("#button-login").click(function(evt) {

          ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (294 bytes)
          GET https://dev.duracloud.org/duradmin/ HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin
          
          
          Request body (0 bytes)
          Response
          Status line and header section (721 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Set-Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF; Path=/duradmin; Secure; HttpOnly
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          username
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        3. GET https://dev.duracloud.org/duradmin/?error
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSERNAME\b and was detected in the element starting with: "<script type="text/javascript">

          $(function() {

          $("#username").focus();

          $("#button-login").click(function(evt) {

          ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (359 bytes)
          GET https://dev.duracloud.org/duradmin/?error HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/login
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (630 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          username
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        4. GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.dc.common.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected in the element starting with: " * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (381 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.dc.common.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 17903
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"17903-1574428024000"
          Last-Modified: Fri, 22 Nov 2019 13:07:04 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (17903 bytes)
          /*
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           *
           * @author "Daniel Bernstein (dbernstein@duraspace.org)"
           */
          
          var dc;
          
          $(function(){
          	(function(){
          		///////////////////////////////////////////////////////////////////////
          		////duracloud js utils
          		///////////////////////////////////////////////////////////////////////
          		if(dc == undefined){
          			dc = {};
          		}
          
          
          		dc.log = function(message){
          			if(window.console){
          				console.log(message);
          			}
          		};
          
          		dc.debug = function(message){
          			if(window.console){
          				if(window.opera){
          					console.log(message);
          				}else{
          				    if(console.debug){
          	                    console.debug(message);
          				    }else{
          				        console.log(message);
          				    }
          				}
          			}
          		};
          
          	    dc.logXhr = function(xhr, message){
                     dc.error("status="+xhr.status + "; statusText="+xhr.statusText);
          	    };
          
          		dc.error = function(message){
          			if(window.console){
          				if(window.opera){
          					console.log(message);
          				}else{
          					console.error(message);
          				}
          			}
          		};
          
              dc.checkSession = function(data){
                if(data != undefined && data != null){
                  if(data.responseText){
                    data = data.responseText;
                  }
                  if(data.toString().indexOf("loginForm") > -1){
                    alert("Your session has timed out.");
                    window.location.reload();
                  }
                }
              };
          
          		dc.displayErrorDialog = function(xhr, textStatus, errorThrown, showStackTrace){
          			var errorText = xhr.responseText;
          
          
          			if(!textStatus){
          			    textStatus = "An unexpected error occurred:";
          			}
          
          			if(showStackTrace == undefined || showStackTrace == null){
          			  showStackTrace = true;
          			}
          
          			try{
          				var response = $.parseJSON(errorText);
          				errorText = "cause: " + response['exception.message'];
          				errorText += "; stacktrace: " + response['exception.stacktrace'];
          			}catch(error){
          
          			}
          
                dc.error("error: " +
                         errorThrown +
                         "; response=" +
                         errorText);
          
          	     var options = {
          	                    autoOpen: true,
          	                    show: 'fade',
          	                    hide: 'fade',
          	                    width:500,
          	                    resizable: true,
          	                    closeOnEscape:true,
          	                    modal: true,
          	                    buttons: {
          	                      "Close": function(){
          	                        $(this).dialog("close");
          	                        errorDialog.empty();
          	                      },
          	                    },
          	                  };
          
          
          			var errorDialog = $.fn.create("div");
          
          			$(document).append(errorDialog);
          			errorDialog.append("<h2>"+textStatus+"</h2>");
          
                if(showStackTrace){
          
                  errorDialog.append("<div><button>Show Details</button>" +
                                     "<div class='error-detail' style='overflow:auto;height:200px;display:none'>" +
                                     "<pre>"+errorText+"</pre></div>");
          
                  errorDialog.find("button").click(function(){
                    errorDialog.find(".error-detail").show();
                  });
          
                  options = $.extend(options, {
                    height: 350
                  });
                }
          
          
          			errorDialog.dialog(options);
          		};
          
          
          		dc.ajax2 = function(settings){
          		    return $.ajax(settings)
                            .error(function(data){
                              dc.checkSession(data);
                            })
                            .done(function(data) {
                              dc.checkSession(data);
                            });
          
          		};
          
          		dc.ajax = function(innerCallback, outerCallback){
          			var callback = $.extend(
          					true,
          					{},
          					innerCallback,
          					{
          						success: function(data, status, xhr){
          							dc.checkSession(data);
          							if(innerCallback.success != undefined){
          								innerCallback.success(data, status, xhr);
          							}else{
          								if(outerCallback != undefined
          										&& outerCallback.success != undefined){
          									outerCallback.success(data, status, xhr);
          								}
          							}
          						},
          						error: function(xhr, textStatus, errorThrown){
          							dc.error(xhr.responseText);
          							if(innerCallback.failure != undefined){
          								innerCallback.failure(textStatus, xhr, errorThrown);
          							}else if(outerCallback != undefined
          										&& outerCallback.failure != undefined){
          									outerCallback.failure(textStatus, xhr, errorThrown);
          							}else{
          								//default error handler
          								dc.done();
          								dc.displayErrorDialog(xhr, textStatus, errorThrown);
          							}
          						},
          
          						begin: (innerCallback.begin != undefined ? innerCallback.begin :
          								(outerCallback != undefined && outerCallback.begin != undefined ? outerCallback.begin : undefined)),
          					}
          			);
          
          			if(callback.begin != undefined){
          				callback.begin();
          			}
          
          			return $.ajax(callback);
          		};
          		/**
          		 * Create a cookie with the given name and value and other optional parameters.
          		 *
          		 * @example dc.cookie('the_cookie', 'the_value');
          		 * @desc Set the value of a cookie.
          		 * @example dc.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
          		 * @desc Create a cookie with all available options.
          		 * @example dc.cookie('the_cookie', 'the_value');
          		 * @desc Create a session cookie.
          		 * @example dc.cookie('the_cookie', null);
          		 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
          		 *       used when the cookie was set.
          		 *
          		 * @param String name The name of the cookie.
          		 * @param String value The value of the cookie.
          		 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
          		 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
          		 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
          		 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
          		 *                             when the the browser exits.
          		 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
          		 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
          		 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
          		 *                        require a secure protocol (like HTTPS).
          		 * @author Klaus Hartl/klaus.hartl@stilbuero.de - modified by Daniel Bernstein
          		 */
          		dc.cookie = function(name, value, options) {
          		    if (typeof value != 'undefined') { // name and value given, set cookie
          		        options = options || {};
          		        if (value === null) {
          		            value = '';
          		            options.expires = -1;
          		        }
          		        var expires = '';
          		        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
          		            var date;
          		            if (typeof options.expires == 'number') {
          		                date = new Date();
          		                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
          		            } else {
          		                date = options.expires;
          		            }
          		            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
          		        }
          		        // CAUTION: Needed to parenthesize options.path and options.domain
          		        // in the following expressions, otherwise they evaluate to undefined
          		        // in the packed version for some reason...
          		        var path = options.path ? '; path=' + (options.path) : '';
          		        var domain = options.domain ? '; domain=' + (options.domain) : '';
          		        var secure = options.secure ? '; secure' : '';
          		        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
          		    } else { // only name given, get cookie
          		        var cookieValue = null;
          		        if (document.cookie && document.cookie != '') {
          		            var cookies = document.cookie.split(';');
          		            for (var i = 0; i < cookies.length; i++) {
          		                var cookie = jQuery.trim(cookies[i]);
          		                // Does this cookie string begin with the name we want?
          		                if (cookie.substring(0, name.length + 1) == (name + '=')) {
          		                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          		                    break;
          		                }
          		            }
          		        }
          		        return cookieValue;
          		    }
          		};
          
          		dc.createTable = function(data, /*optional: array*/ columnDefs){
          			var table, body, row, i,j;
          			table = $.fn.create("table");
          			if(columnDefs){
          				row = $.fn.create("tr");
          				$.each(columnDefs, function(x,item){
          					var h = $.fn.create("th").html(item.name);
          					if(item.cssClass){
          						//h.addClass(item.cssClass);
          					}
          					row.append(h);
          				});
          				table.append($.fn.create("thead").append(row));
          			}
          
          			body = $.fn.create("tbody");
          			table.append(body);
          
          			for(i = 0; i < data.length; i++){
          				row = $.fn.create("tr");
          				$(body).append(row);
          				for(j = 0; j < data[i].length; j++){
          					var value = data[i][j],
          							cell = $.fn.create("td");
          
          					$(row).append(cell);
          
          					if(columnDefs && columnDefs[j]){
          						if(columnDefs[j].formatter){
          							value = columnDefs[j].formatter(value);
          						}
          
          						if(columnDefs[j].cssClass){
          							cell.addClass(columnDefs[j].cssClass);
          						}
          					}
          					cell.append(value);
          				}
          			}
          			return table;
          		};
          
          		dc.getMimetypeImageClass = function(mimetype){
          		var mtc = "";
          		if(mimetype.indexOf("audio") > -1){
          			mtc = "audio";
          		}else if(mimetype.indexOf("image") > -1){
          			mtc ="image";
          		}else if(mimetype.indexOf("video") > -1){
          			mtc = "video";
          		}else if(mimetype.indexOf("xml") > -1){
          			mtc = "xml";
          		}else if(mimetype.indexOf("zip") > -1){
          			mtc = "compression";
          		}else{
          			mtc = "generic";
          		}
          		return "mime-type-" + mtc;
          
          		};
          
          		var spNameMap = {};
          		spNameMap["AMAZON_S3"] = "Amazon S3";
          		spNameMap["AMAZON_GLACIER"] = "Amazon Glacier";
                          spNameMap["SWIFT_S3"] = "Swift S3";
          		spNameMap["CHRONOPOLIS"] = "Chronopolis";
          		spNameMap["IRODS"] = "iRODS";
          		dc.STORAGE_PROVIDER_KEY_MAP = spNameMap;
          
          
          		dc.formatGB = function(value, decimalplaces, showUnits){
          			if(!decimalplaces){
          				decimalplaces = 0;
          			}
          
          			if(showUnits == undefined){
          				showUnits = true;
          			}
          
          			value = new Number(value/(1000*1000*1000));
          			value =  value.toFixed(parseInt(decimalplaces));
          
          			if(showUnits){
          				return value +"GB";
          			}else{
          				return value;
          			}
          		};
          
          		dc.busy = function(message, options){
          			var d =
          			   $("#busy-dialog");
          			var modal = false;
          			var buttons = undefined;
          
          			if(options != undefined){
          				if(options.modal != undefined){
          					modal = options.modal;
          				}
          
          				if(options.buttons != undefined){
          					buttons = options.buttons;
          				}
          			}
          
          			var dOptions = {
          					autoOpen: false,
          					show: 'fade',
          					hide: 'fade',
          					resizable: false,
          					height: 100,
          					closeOnEscape:false,
          					modal: modal != undefined ? modal : false,
          					width:300,
          					close: function() {
          
          					},
          
          					open: function(e){
          					},
          			};
          
          			if(buttons != undefined){
          				dOptions.buttons = buttons;
          			}
          
          			d.dialog(dOptions);
          
          		   $("#busy-dialog-title").html(message);
          
          		   if(!d.dialog("isOpen")){
          		       d.dialog("open");
          		   }
          		};
          
          		dc.done = function(message){
          			$("#busy-dialog").dialog("close");
          
          			if(message != undefined){
          				var d = $("#message-dialog");
          				d.dialog({
          					autoOpen: false,
          					show: 'fade',
          					hide: 'fade',
          					resizable: false,
          					height: 100,
          					closeOnEscape:true,
          					modal: false,
          					width:300,
          					buttons: {
          						"Close" : function(){
          							$(this).dialog('close');
          						 },
          					},
          					close: function() {},
          					open: function(e){},
          				});
          
          			   $("#message-dialog-title").html(message);
          			   d.dialog("open");
          			}
          		};
          
          
          		dc.confirm = function(message,evt){
          			if(!confirm(message)){
          				if(evt != undefined){
          					evt.stopPropagation();
          					evt.preventDefault();
          				}
          				return false;
          			};
          
          			return true;
          		};
          
          
                  dc.extractStoreId = function(path){
                      var index = path.indexOf("?storeId=");
                      if(index > 0){
                          return path.substring(index+9);
                      }else{
                          return null;
                      }
                  };
          
          	    dc.extractSpaceId = function(path){
          	        var index = path.indexOf("/");
          	        return path.substring(0, index);
          	    };
          
          	    dc.extractContentId = function(path){
          	        var index = path.indexOf("/");
          	        var qsIndex = path.indexOf("?");
          	        return path.substring(index+1, (qsIndex > 0 ? qsIndex : path.length));
          	    };
          
          	    dc.reportOverlayOnClick = function(link, storeId, spaceId){
                      var params = "&spaceId=" + spaceId;
                      if(storeId){
                          params+="&storeId="+storeId;
                      }
          
                      var prefix = "/duradmin/servicesreport";
          
                      var fileInfoUrl = prefix + "/info?" + params;
          
                      var jqxhr = $.getJSON(fileInfoUrl, function(data){
                          var size = new Number(data.fileInfo.size);
                          if(size > (1024*1000)){
                              link.attr("href", prefix + "/raw?attachment=true&" + params);
                          }else{
                              var url = prefix + "/htmltable?" + params;
                              link.attr("href", url)
                                  .attr("title","View Bit Integrity Report")
                                  .fancybox({type: 'iframe',
                                             width: 800,
                                             scrolling: 'auto',
                                             titleShow: false,
                                          });
                          }
                      });
          	    };
          
          		/**
          		 * checks the progress of a remote task and notifies caller of results.
          		 */
          		var DEFAULT_POLL_INTERVAL = 5000;
          
          		dc.checkProgress = function(url, key, callback){
          
          			if(callback.count == undefined){
          				callback.count = 0;
          			}
          
          			var updater = function(progressCallback, data){
          				if(data.error){
          					_error(data.message);
          					progressCallback.failure(message);
          					return;
          				}
          
          				progressCallback.update(data);
          				if(data.task != undefined){
          					var state = data.task.properties.state;
          
          					if(state == 'running' || state == 'initialized'){
          						setTimeout(function(){ dc.checkProgress(url,key, progressCallback); }, DEFAULT_POLL_INTERVAL);
          					}else if(state == 'success'){
          						if(progressCallback.success != undefined){
          							progressCallback.success(data);
          						}
          					}else if(state == 'cancelled'){
          						if(progressCallback.cancel != undefined){
          							progressCallback.cancel();
          						}
          					}else{
          						if(progressCallback.failure != undefined){
          							progressCallback.failure();
          						}
          					}
          				}
          			};
          
          			dc.ajax({ url: url,
          				cache: false,
          				type: "GET",
          				success: function(data){
          					//ajax response gets set here
          					updater(callback, data);
          			    },
          			    failure: function(textStatus){
          			    	alert("updater failed: " + textStatus);
          			    },
          			});
          		};
          
                  /**
                  * Login function
                  *
                  * @return jqXHR Jquery XmlHttpRequest object.
                  */
                  dc.login = function(/* jquery object */form) {
                      var message = $("#msg-error");
                      var feedback = $("#feedback");
                      return $.ajax({
                          type : "POST",
                          url : form.attr("action"),
                          data : form.serialize(),
                          cache : false,
                          beforeSend : function() {
                              message.makeHidden();
                              feedback.fadeIn();
                          },
                          complete : function() {
                              feedback.fadeOut();
                          },
                          success : function(data, textStatus, jqXHR) {
                              try {
                                  dc.debug("data=" + data);
                                  if (data.indexOf(form.attr("id")) > 0) {
                                      message.makeVisible();
                                      message.fadeIn();
                                  } else {
                                      location.reload(true);
                                  }
                              } catch (err) {
                                  dc.error(err);
                                  dc.displayErrorDialog(jqXHR, textStatus,
                                          "An unexpected error occurred: " + err);
                              }
                          },
                          error : function(jqXHR, text, errorThrown) {
                              dc.displayErrorDialog(jqXHR, text, errorThrown);
                          },
                      });
                  };
          
          
                  dc.formatBytes = function(bytes, showBytes){
                      var val = null;
                      bytes = new Number(bytes);
                      var bytesValue = bytes + " bytes";
          
                      if(bytes < 1000){
                          return bytesValue;
                      }else if(bytes < 1000*1000){
                         val = (bytes/1000).toFixed(1) + " KB";
                      }else if(bytes < 1000*1000*1000){
                          val = (bytes/(1000*1000)).toFixed(1) + " MB";
                      }else{
                          val = (bytes/(1000*1000*1000)).toFixed(1) + " GB";
                      }
          
                      if(showBytes){
                          val += " (" + bytesValue + ")";
                      }
                      return val;
                  };
          
          
                  dc.hexEncode = function(val) {
                    var hex, i;
          
                    var result = "";
                    for (i = 0; i < val.length; i++) {
                      hex = val.charCodeAt(i).toString(16);
                      result += ("000" + hex).slice(-4);
                    }
          
                    return result
                  };
          
                dc.hexDecode = function(val) {
                  var j;
                  var hexes = val.match(/.{1,4}/g) || [];
                  var back = "";
                  for (j = 0; j < hexes.length; j++) {
                    back += String.fromCharCode(parseInt(hexes[j], 16));
                  }
          
                  return back;
                };
          
          	})();
          });
          
          
          
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        5. GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.fn.ext.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSER\b and was detected in the element starting with: " * Closes the dialog when the user clicks off of it.", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (378 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/ext/jquery.fn.ext.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 5462
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"5462-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (5462 bytes)
          /*
           * The contents of this file are subject to the license and copyright
           * detailed in the LICENSE and NOTICE files at the root of the source
           * tree and available online at
           *
           *     http://duracloud.org/license/
           */
          
          /**
           * A collection of useful jquery extensions
           * @author "Daniel Bernstein (dbernstein@duraspace.org)"
           */
          
          
          $(function(){
          	(function(){
          		////////////////////////////////////////////////////////////////////
          		//jquery extensions
          		///////////////////////////////////////////////////////////////////
          	    $.fn.disable = function(/*boolean*/ val){
          	        if(!val){
          	           return $(this).removeAttr("disabled");
          	        }else{
          	           return $(this).attr("disabled", "disabled");
          	        }
          	    };
          	    
          	    /**
          		 * Similar to hide/show jquery functions but toggles the visibility css 
          		 * attribute instead of the display attribute.
          		 */
          		$.fn.makeVisible = function(isvisible) {
          			return $(this).css("visibility", (isvisible == undefined || isvisible) ? "visible":"hidden");
          		};
          		
          		$.fn.makeHidden = function() {
          			return $(this).makeVisible(false);
          		};
          
          		
          		/**
          		 * This finds the nearest ancestor of the specified class.  It is just like jQuery.closest(selector) except
          		 * that it includes the dom node your are calling the function on.
          		 */
          		$.fn.nearestOfClass = function(className){
          			var nearest = (this.hasClass(className)) ? this : this.closest("." + className);
          			return $(nearest);
          		};
          
          		
          		$.fn.toggleOpenClosed = function(){
          			$(this).nearestOfClass("button")
          					.toggleClass("dialog-open")
          					.toggleClass("dialog-closed");
          		};
          
          		/**
          		 * Shorthand for document.createElement
          		 * Returns the new element as a jQuery object.
          		 */
          		$.fn.create = function(tag){
          			return $(document.createElement(tag));
          			
          		};
          		
          		/**
          		 * Scrolls the specified dom element to the top of the 
          		 * viewport (which is the object on which you're calling this function)
          		 * if possible. If it can't scroll it to the top of the viewport it at 
          		 * least scrolls the container so that the element is in view.
          		 * @param DOM node or jquery object
          		 */
          		$.fn.scrollTo = function(element){
          			var top = $(element).offset().top;
          			this.animate({scrollTop: top}, {duration:"slow", easing:"swing", queue:true});
          		};
          
          		/**
          		 * Returns true if the element is in the viewport
          		 */
           		$.fn.isVisibleInViewPort = function() {
           		        var rect = this.get(0).getBoundingClientRect();
          
           		        return rect.bottom > 0 &&
           		            rect.right > 0 &&
           		            rect.left < (window.innerWidth || document. documentElement.clientWidth) /*or $(window).width() */ &&
           		            rect.top < (window.innerHeight || document. documentElement.clientHeight) /*or $(window).height() */;
           		}
          
          		/**
          		 * this method loads the children of the new contents
          		 * into the target after emptying the contents
          		 * with a fade in / fade out effect
          		 */
          		$.fn.replaceContents = function(/*the pane whose contents will be swapped in*/ newContents,  
          										/*the layout for the target*/ layoutOptions){
          			var target = this;
          			//$(target).fadeOut("fast", function(){
          				$(target).empty().prepend($(newContents).children());
          				//$(target).fadeIn("fast");
          				if(layoutOptions != null && layoutOptions != undefined){
          					$(target).layout(layoutOptions);
          				}
          			//});
          			return $(target);
          		};	
          
          		/**
          		 * Closes the dialog when the user clicks off of it.
          		 */
          		$.fn.closeOnLostFocus = function() { // on the open event
          		    // find the dialog element
          		    var dialogEl = this;        
          		    $(document).click(function (e) { // when anywhere in the doc is clicked
          		        var clickedOutside = true; // start searching assuming we clicked outside
          		        $(e.target).parents().andSelf().each(function () { // search parents and self
          		            // if the original dialog selector is the click's target or a parent of the target
          		            // we have not clicked outside the box
          		            if ($(this).first().attr("id") == $(dialogEl).attr("id")) {
          		                clickedOutside = false; // found
          		                return false; // stop searching
          		            }
          		        });
          		        if (clickedOutside) {
          		            $(dialogEl).dialog("close"); // close the dialog
          		            // unbind this listener, we're done with it
          		            $(document).unbind('click',arguments.callee); 
          		        }
          		    });
          		};
          		
          		
          		/**
          		 * Binds the enter keyup event to the specified function.
          		 */
          		$.fn.bindEnterKey = function(func) {
          			$(this).bind('keydown', function(e){
          			    if(e.keyCode==13){
          		        	func(e);
          			    }
          			});		
          			
          			return this;
          		};
          		
          		$.fn.busy = function(){
          		    $(".dc-busy",this).show("fast");
          		    return this;
          		};
          
          		$.fn.idle = function(){
                      $(".dc-busy",this).hide();
                      return this;
                  };
          
          
              $.fn.busySibling = function(text){
                var busy = $("<div class='dc-busy-holder'></div>");
                if(text){
                  busy.html(text);
                }
                
                busy.insertAfter($(this));
                busy.show("fast");
                return this;
              };
          
              $.fn.idleSibling = function(){
                $(this).siblings(".dc-busy-holder").hide("fast").remove();
                return this;
              };
          
              //adds in missing addBack function for plugins that depend on it (namely jquery dropdown)
              $.fn.addBack = function (selector) {
                return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
              };
                  
          	})();
          });
          
          
          Evidence
          user
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        6. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bSELECT\b and was detected 4 times, the first in the element starting with: " select: function(select){", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (385 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 11271
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"11271-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (11271 bytes)
          /**
           * 
           * created by Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///selectable list widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          (function(){
          /**
           * Selectable list widget
           */
          $.widget("ui.selectablelist",{
          	
          	/**
          	 * Default values go here
          	 */
          	options: {
          	
          			itemClass: "dc-item"
          		,   selectable: true
          		,   clickable: true
          		,   itemActionClass: "dc-action-panel"
          			
          	},
          	
          	_currentItem: null,
          	_footer: null,
          	dataMap: new Array(),
          	
          	_restyleSiblings: function(siblings){
          		siblings.removeClass("dc-selected-list-item dc-checked-selected-list-item dc-checked-list-item");
          		siblings.find("input[type='checkbox']:checked").closest("." +this.options.itemClass).addClass("dc-checked-list-item");
          	},
          	
          	_styleItem:  function(target){
          		if(target != undefined && target != null){
          			var item = $(target).nearestOfClass(this.options.itemClass);
          			$(item).removeClass("dc-checked-selected-list-item dc-checked-list-item dc-selected-list-item");
          			var checked = $(item).find("input[type='checkbox']:checked").size() > 0;
          			$(item).addClass(checked ? "dc-checked-selected-list-item" : "dc-selected-list-item");
          			this._restyleSiblings(item.siblings());
          		}else{
          			this._restyleSiblings(this.element.children("."+this.options.itemClass));
          		}
          		
          	},
          
          	_getSelectedItems: function(){
          		var array =  new Array();
          		var items = this.element.find("."+this.options.itemClass).toArray();
          		$.each(items, function(i, e){
          			if($(e).find("input[type='checkbox']:checked").size() > 0){
          				array.push(e);
          			}
          		});
          
          		return array;
          	},
          	
          	getSelectedData: function(){
          		var that = this;
          		var selected = this._getSelectedItems();
          		var selectedData = new Array();
          		$.each(selected, function(i,selectedItem){
          			selectedData.push(that._getDataById($(selectedItem).attr("id")));
          		});
          		
          		return selectedData;
          	},
          	
          	_setCurrentItem: function(item){
              this._currentItem = {
                                   item:item, 
                                   data: this._getDataById($(item).attr("id")),
                                 };
          	},
          	
          	_fireCurrentItemChanged: function(item, notify){
          		
          		if(item != null){
          		  this._setCurrentItem(item);
          		}else{
          			this._currentItem = null;
          		}
          		
          		
          		$("input[type='checkbox']:checked",this.element).removeAttr("checked");
          		this._styleItem(item);
          		if(item){
          		    $(item).find("input[type='checkbox']")
          		           .not("[disabled]")
          		           .attr("checked",true);
          		}
          
                  var selectedItems = this._getSelectedItems();
          		
          		var fire = (notify == undefined || notify == null || notify == true);
          		if(fire){
          			this.element.trigger(
          				"currentItemChanged",
          				{	
          					currentItem:this._currentItem, 
          					selectedItems: selectedItems
          				}
          			);
          		}
          	},
          	
          	_fireSelectionChanged: function(){
          	  var selectedItems = this._getSelectedItems();
              
          		if(selectedItems.length == 0){
          		    this._fireCurrentItemChanged(null, false);
          		}else if(selectedItems.length == 1){
          		 this._currentItem = this._setCurrentItem(selectedItems[0]);
          		}
          		
          		var ci = this._currentItem;
              this._styleItem(ci != null && ci.item != null ? ci.item : null);
              
          		
          		this.element.trigger(
          			"selectionChanged", 
          			{
          				selectedItems: this._getSelectedItems(), 
          				currentItem: this._currentItem,
          			}
          		);
          	},
          
          	_fireItemRemoved: function(item, data){
          		this.element.trigger(
          		  "itemRemoved", 
          		  {
          		      item: item,
          		      data: data,
          		  }
          	    );
          	},
          
          
          
          	_itemSelectionStateChanged: function(target){
          		var item = $(target).closest("."+this.options.itemClass);
          		this._fireSelectionChanged(item);
          	},
          	
          	clear: function(notify){
          		this._currentItem = null;
          		this.element.children("."+this.options.itemClass).remove();	
                  this.element.children("."+this.options.itemClass + "-divider").remove(); 
          		this.dataMap = new Array();
          		this._fireCurrentItemChanged(null,notify);
          		$(this._footer).html('');
          	},
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		this.clear(false);
          
          		this._footer = $.fn.create("div").addClass("dc-selectablelist-footer").html("");
          		$(that.element).append(that._footer);
          		
          		//add item classes to all direct children
          		$(that.element).children("."+this.options.itemClass).each(function(i,c){
          			that._initItem(c);
          		});
          		
          		that.element.unbind().bind("selectionChanged", function(evt, state){
          			var selectionChanged = that.options.selectionChanged;
          			if(selectionChanged){
          				selectionChanged(evt,state);
          			}
          		});
          		
          	},
          	
          
              	addItem : function(item, 
              	                   data, 
              	                   selected, 
              	                   /* optional boolean */disabled, 
              	                   /*optional boolean*/noIndent, //suppresses indentation for non-selectable items.
              	                   /*optional String*/ dividerLabel //specifies label of the section 
              	                                                    //into which the item should be inserted.
              	                   ) {
              	var that = this;
                this.setFooter('');
                if(dividerLabel){
                  var dividers = [];
                  $("." + this.itemDividerClass(), this.element).each(function(i,e){
                      dividers.push(e);
                  });
                  
                  if(dividers.length > 0){
                    
                    $.each(dividers, function(i, div){
                      if($(div).html() == dividerLabel){
                         if(i == dividers.length-1){
                           that._footer.before(item);
                         }else{
                           $(dividers[i+1]).before(item);
                         }
                         
                         return false;
                      }
                    });
                  }else{
                    this._footer.before(item);
                  }
                
          
                  if (selected && this.options.selectable) {
                    $("input[type=checkbox]", item).attr("checked", true);
                  }
                  
                }else{
                    this._footer.before(item);
                }
          
                this._initItem(item, data, disabled, noIndent);
          
                return item;
              },
              
              itemDividerClass: function(){
                return this.options.itemClass+"-divider";
              },
          	
              addDivider: function(label){
                  this.setFooter('');
                  
                  var divider = $.fn.create("div").addClass(this.itemDividerClass());
                  divider.html(label);
                  this._footer.before(divider);
              },
          	
          	select: function(select){
          		var that = this;
          		that._select(select);
          		that._fireSelectionChanged();
          	},
          
              _select: function(select){
                  var that = this;
                  $("input[type=checkbox]",this.element).not("[disabled]").attr("checked",select);
              },
          
          	removeById: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		var data = this._removeDataById(elementId);
          		item.remove();
          		
          		if(this._currentItem){
          		    if($(this._currentItem.item).attr("id") == elementId){
          	            this._fireCurrentItemChanged(null);
          		    }
          		}
          		this._fireItemRemoved(item, data);
          	},
          
          	idExists: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		if(item){
          			return true;
          		}else{
          			return false;
          		}
          	},
          
          
          	_getDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_removeDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				this.dataMap.splice(i,1);
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_putData: function(id,data){
          		this.dataMap[this.dataMap.length] = { key: id, value: data};
          	},
          	
          	setCurrentItemById: function(id, notify){
          	    if(this._currentItem){
          	        if(this._currentItem.item.attr("id") == id){
          	            return;
          	        }
          	    }
          		this._fireCurrentItemChanged($("#"+id, this.element), notify);
          	},
          	
          	setFirstItemAsCurrent: function(){
          		 var first = this.element.children("."+this.options.itemClass).first();
          		 if(first != undefined && first !=null){
          			 this._fireCurrentItemChanged(first, true);
          		 }
          	},
          
          	lastItemData: function(){
          		 var last = this.lastItem();
          		 if(last != undefined && last != null){
          			 return this._getDataById($(last).attr("id"));
          		 }
          		 return null;
          	},
          	
          	lastItem: function(){
          		 return this.element.children("."+this.options.itemClass).last();
          	},
          
          	length: function(){
          		 return this.element.children("."+this.options.itemClass).size();
          	},
          
          	
          	currentItem:function(){
          		return this._currentItem;
          	},
          	
          	setFooter:function(footerContent){
          		this._footer.html('');
          		$(this._footer).append(footerContent);
          	},
          
          	_initItem : function(item, data, selectionDisabled, noIndent) {
                var that = this;
                var o = this.options;
                var itemClass = o.itemClass;
                var actionClass = o.itemActionClass;
                var checkbox;
                var checkboxHolder;
          
                if (selectionDisabled == undefined || selectionDisabled == null) {
                  selectionDisabled = false;
                }
          
                $(item).addClass(itemClass);
          
                if (this.options.selectable && !(selectionDisabled && noIndent)) {
                  var checkbox = $("<input type='checkbox'/>");
                  checkbox.attr("aria-labelledby", item.attr("id"));
                  //checkbox holder serves to create a clickable
                  //buffer zone around the checkbox in order to
                  //make it easier for the user to check.
                  var checkboxHolder = $("<span class='cb-holder'></span>");
                  checkboxHolder.append(checkbox);
                  $(item).prepend(checkboxHolder);
          
                  if (selectionDisabled != undefined) {
                    checkbox.disable(selectionDisabled);
                    if (selectionDisabled) {
                      checkbox.makeHidden();
                    } else {
                      checkboxHolder.click(function(evt) {
                        if (evt.target == this) {
                          if (checkbox.is(":checked")) {
                            checkbox.removeAttr("checked");
                          } else {
                            checkbox.attr("checked", "checked");
                          }
                          that._itemSelectionStateChanged(checkbox);
                        }
                        evt.stopPropagation();
                      });
                    }
                  }
          
                  $(item).children().first().change(function(evt) {
                    that._itemSelectionStateChanged(evt.target);
                    evt.stopPropagation();
                  });
                }
          
                $(item).children("div").last().addClass("float-r").addClass(actionClass);
          
                var clickHandler = function(evt) {
                  var item = $(evt.target).nearestOfClass(itemClass);
                  if ($(evt.target).attr("type") != "checkbox") {
          
                    if (that.options.clickable) {
                      if (that.options.selectable) {
                        that._select(false);
                        item.find(":checkbox").not("[disabled]").attr("checked", true);
                      }
          
                      that._fireCurrentItemChanged(item);
                    }
          
                    evt.stopPropagation();
                  }
                };
          
                //bind mouse action listeners
                $(item).find("." + actionClass).andSelf().click(clickHandler).dblclick(clickHandler).mouseover(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeVisible();
                }).mouseout(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeHidden();
                });
          
                //hide all actions to start
                $(item).find("." + actionClass).makeHidden();
          
                //add the data to the map
                that._putData($(item).attr("id"), data);
                return item;
              }
          });
          
          })();
          
          
          
          Evidence
          select
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        7. GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSER\b and was detected in the element starting with: " //make it easier for the user to check.", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (385 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/dc/widget/ui.selectablelist.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 11271
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"11271-1616675498000"
          Last-Modified: Thu, 25 Mar 2021 12:31:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (11271 bytes)
          /**
           * 
           * created by Daniel Bernstein
           */
          
          /////////////////////////////////////////////////////////////////////////////////////
          ///selectable list widget
          ///
          /////////////////////////////////////////////////////////////////////////////////////
          (function(){
          /**
           * Selectable list widget
           */
          $.widget("ui.selectablelist",{
          	
          	/**
          	 * Default values go here
          	 */
          	options: {
          	
          			itemClass: "dc-item"
          		,   selectable: true
          		,   clickable: true
          		,   itemActionClass: "dc-action-panel"
          			
          	},
          	
          	_currentItem: null,
          	_footer: null,
          	dataMap: new Array(),
          	
          	_restyleSiblings: function(siblings){
          		siblings.removeClass("dc-selected-list-item dc-checked-selected-list-item dc-checked-list-item");
          		siblings.find("input[type='checkbox']:checked").closest("." +this.options.itemClass).addClass("dc-checked-list-item");
          	},
          	
          	_styleItem:  function(target){
          		if(target != undefined && target != null){
          			var item = $(target).nearestOfClass(this.options.itemClass);
          			$(item).removeClass("dc-checked-selected-list-item dc-checked-list-item dc-selected-list-item");
          			var checked = $(item).find("input[type='checkbox']:checked").size() > 0;
          			$(item).addClass(checked ? "dc-checked-selected-list-item" : "dc-selected-list-item");
          			this._restyleSiblings(item.siblings());
          		}else{
          			this._restyleSiblings(this.element.children("."+this.options.itemClass));
          		}
          		
          	},
          
          	_getSelectedItems: function(){
          		var array =  new Array();
          		var items = this.element.find("."+this.options.itemClass).toArray();
          		$.each(items, function(i, e){
          			if($(e).find("input[type='checkbox']:checked").size() > 0){
          				array.push(e);
          			}
          		});
          
          		return array;
          	},
          	
          	getSelectedData: function(){
          		var that = this;
          		var selected = this._getSelectedItems();
          		var selectedData = new Array();
          		$.each(selected, function(i,selectedItem){
          			selectedData.push(that._getDataById($(selectedItem).attr("id")));
          		});
          		
          		return selectedData;
          	},
          	
          	_setCurrentItem: function(item){
              this._currentItem = {
                                   item:item, 
                                   data: this._getDataById($(item).attr("id")),
                                 };
          	},
          	
          	_fireCurrentItemChanged: function(item, notify){
          		
          		if(item != null){
          		  this._setCurrentItem(item);
          		}else{
          			this._currentItem = null;
          		}
          		
          		
          		$("input[type='checkbox']:checked",this.element).removeAttr("checked");
          		this._styleItem(item);
          		if(item){
          		    $(item).find("input[type='checkbox']")
          		           .not("[disabled]")
          		           .attr("checked",true);
          		}
          
                  var selectedItems = this._getSelectedItems();
          		
          		var fire = (notify == undefined || notify == null || notify == true);
          		if(fire){
          			this.element.trigger(
          				"currentItemChanged",
          				{	
          					currentItem:this._currentItem, 
          					selectedItems: selectedItems
          				}
          			);
          		}
          	},
          	
          	_fireSelectionChanged: function(){
          	  var selectedItems = this._getSelectedItems();
              
          		if(selectedItems.length == 0){
          		    this._fireCurrentItemChanged(null, false);
          		}else if(selectedItems.length == 1){
          		 this._currentItem = this._setCurrentItem(selectedItems[0]);
          		}
          		
          		var ci = this._currentItem;
              this._styleItem(ci != null && ci.item != null ? ci.item : null);
              
          		
          		this.element.trigger(
          			"selectionChanged", 
          			{
          				selectedItems: this._getSelectedItems(), 
          				currentItem: this._currentItem,
          			}
          		);
          	},
          
          	_fireItemRemoved: function(item, data){
          		this.element.trigger(
          		  "itemRemoved", 
          		  {
          		      item: item,
          		      data: data,
          		  }
          	    );
          	},
          
          
          
          	_itemSelectionStateChanged: function(target){
          		var item = $(target).closest("."+this.options.itemClass);
          		this._fireSelectionChanged(item);
          	},
          	
          	clear: function(notify){
          		this._currentItem = null;
          		this.element.children("."+this.options.itemClass).remove();	
                  this.element.children("."+this.options.itemClass + "-divider").remove(); 
          		this.dataMap = new Array();
          		this._fireCurrentItemChanged(null,notify);
          		$(this._footer).html('');
          	},
          	
          	/**
          	 * Initialization 
          	 */
          	_init: function(){
          		var that = this;
          		this.clear(false);
          
          		this._footer = $.fn.create("div").addClass("dc-selectablelist-footer").html("");
          		$(that.element).append(that._footer);
          		
          		//add item classes to all direct children
          		$(that.element).children("."+this.options.itemClass).each(function(i,c){
          			that._initItem(c);
          		});
          		
          		that.element.unbind().bind("selectionChanged", function(evt, state){
          			var selectionChanged = that.options.selectionChanged;
          			if(selectionChanged){
          				selectionChanged(evt,state);
          			}
          		});
          		
          	},
          	
          
              	addItem : function(item, 
              	                   data, 
              	                   selected, 
              	                   /* optional boolean */disabled, 
              	                   /*optional boolean*/noIndent, //suppresses indentation for non-selectable items.
              	                   /*optional String*/ dividerLabel //specifies label of the section 
              	                                                    //into which the item should be inserted.
              	                   ) {
              	var that = this;
                this.setFooter('');
                if(dividerLabel){
                  var dividers = [];
                  $("." + this.itemDividerClass(), this.element).each(function(i,e){
                      dividers.push(e);
                  });
                  
                  if(dividers.length > 0){
                    
                    $.each(dividers, function(i, div){
                      if($(div).html() == dividerLabel){
                         if(i == dividers.length-1){
                           that._footer.before(item);
                         }else{
                           $(dividers[i+1]).before(item);
                         }
                         
                         return false;
                      }
                    });
                  }else{
                    this._footer.before(item);
                  }
                
          
                  if (selected && this.options.selectable) {
                    $("input[type=checkbox]", item).attr("checked", true);
                  }
                  
                }else{
                    this._footer.before(item);
                }
          
                this._initItem(item, data, disabled, noIndent);
          
                return item;
              },
              
              itemDividerClass: function(){
                return this.options.itemClass+"-divider";
              },
          	
              addDivider: function(label){
                  this.setFooter('');
                  
                  var divider = $.fn.create("div").addClass(this.itemDividerClass());
                  divider.html(label);
                  this._footer.before(divider);
              },
          	
          	select: function(select){
          		var that = this;
          		that._select(select);
          		that._fireSelectionChanged();
          	},
          
              _select: function(select){
                  var that = this;
                  $("input[type=checkbox]",this.element).not("[disabled]").attr("checked",select);
              },
          
          	removeById: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		var data = this._removeDataById(elementId);
          		item.remove();
          		
          		if(this._currentItem){
          		    if($(this._currentItem.item).attr("id") == elementId){
          	            this._fireCurrentItemChanged(null);
          		    }
          		}
          		this._fireItemRemoved(item, data);
          	},
          
          	idExists: function(elementId) {
          		var item = $("[id='"+elementId+"']", this.element).first();
          		if(item){
          			return true;
          		}else{
          			return false;
          		}
          	},
          
          
          	_getDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_removeDataById: function(id){
          		for(i in this.dataMap){
          			var e = this.dataMap[i];
          			if(e.key == id){
          				this.dataMap.splice(i,1);
          				return e.value;
          			};
          		}
          		return null;
          	},
          
          	_putData: function(id,data){
          		this.dataMap[this.dataMap.length] = { key: id, value: data};
          	},
          	
          	setCurrentItemById: function(id, notify){
          	    if(this._currentItem){
          	        if(this._currentItem.item.attr("id") == id){
          	            return;
          	        }
          	    }
          		this._fireCurrentItemChanged($("#"+id, this.element), notify);
          	},
          	
          	setFirstItemAsCurrent: function(){
          		 var first = this.element.children("."+this.options.itemClass).first();
          		 if(first != undefined && first !=null){
          			 this._fireCurrentItemChanged(first, true);
          		 }
          	},
          
          	lastItemData: function(){
          		 var last = this.lastItem();
          		 if(last != undefined && last != null){
          			 return this._getDataById($(last).attr("id"));
          		 }
          		 return null;
          	},
          	
          	lastItem: function(){
          		 return this.element.children("."+this.options.itemClass).last();
          	},
          
          	length: function(){
          		 return this.element.children("."+this.options.itemClass).size();
          	},
          
          	
          	currentItem:function(){
          		return this._currentItem;
          	},
          	
          	setFooter:function(footerContent){
          		this._footer.html('');
          		$(this._footer).append(footerContent);
          	},
          
          	_initItem : function(item, data, selectionDisabled, noIndent) {
                var that = this;
                var o = this.options;
                var itemClass = o.itemClass;
                var actionClass = o.itemActionClass;
                var checkbox;
                var checkboxHolder;
          
                if (selectionDisabled == undefined || selectionDisabled == null) {
                  selectionDisabled = false;
                }
          
                $(item).addClass(itemClass);
          
                if (this.options.selectable && !(selectionDisabled && noIndent)) {
                  var checkbox = $("<input type='checkbox'/>");
                  checkbox.attr("aria-labelledby", item.attr("id"));
                  //checkbox holder serves to create a clickable
                  //buffer zone around the checkbox in order to
                  //make it easier for the user to check.
                  var checkboxHolder = $("<span class='cb-holder'></span>");
                  checkboxHolder.append(checkbox);
                  $(item).prepend(checkboxHolder);
          
                  if (selectionDisabled != undefined) {
                    checkbox.disable(selectionDisabled);
                    if (selectionDisabled) {
                      checkbox.makeHidden();
                    } else {
                      checkboxHolder.click(function(evt) {
                        if (evt.target == this) {
                          if (checkbox.is(":checked")) {
                            checkbox.removeAttr("checked");
                          } else {
                            checkbox.attr("checked", "checked");
                          }
                          that._itemSelectionStateChanged(checkbox);
                        }
                        evt.stopPropagation();
                      });
                    }
                  }
          
                  $(item).children().first().change(function(evt) {
                    that._itemSelectionStateChanged(evt.target);
                    evt.stopPropagation();
                  });
                }
          
                $(item).children("div").last().addClass("float-r").addClass(actionClass);
          
                var clickHandler = function(evt) {
                  var item = $(evt.target).nearestOfClass(itemClass);
                  if ($(evt.target).attr("type") != "checkbox") {
          
                    if (that.options.clickable) {
                      if (that.options.selectable) {
                        that._select(false);
                        item.find(":checkbox").not("[disabled]").attr("checked", true);
                      }
          
                      that._fireCurrentItemChanged(item);
                    }
          
                    evt.stopPropagation();
                  }
                };
          
                //bind mouse action listeners
                $(item).find("." + actionClass).andSelf().click(clickHandler).dblclick(clickHandler).mouseover(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeVisible();
                }).mouseout(function(evt) {
                  $(evt.target).nearestOfClass(itemClass).find("." + actionClass).makeHidden();
                });
          
                //hide all actions to start
                $(item).find("." + actionClass).makeHidden();
          
                //add the data to the map
                that._putData($(item).attr("id"), data);
                return item;
              }
          });
          
          })();
          
          
          
          Evidence
          user
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        8. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bBUG\b and was detected 7 times, the first in the element starting with: " // set display to none to avoid a layout bug in IE", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          bug
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        9. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bBUGS\b and was detected in the element starting with: " // http://ui.jquery.com/bugs/ticket/3193", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          bugs
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        10. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected 78 times, the first in the element starting with: " // inheriting from", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        11. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bLATER\b and was detected 2 times, the first in the element starting with: " this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          later
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        12. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bSELECT\b and was detected 25 times, the first in the element starting with: " return ( /input|select|textarea|button|object/.test( nodeName )", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          select
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        13. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bTODO\b and was detected 43 times, the first in the element starting with: " // TODO: determine which cases actually cause this to happen", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          TODO
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        14. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSER\b and was detected 9 times, the first in the element starting with: " //If overflow is hidden, the element might have extra content, but the user wants to hide it", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          user
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        15. GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bWHERE\b and was detected 6 times, the first in the element starting with: " // Ignore z-index if position is set to a value where z-index is ignored by the browser", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (367 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery-ui.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (453 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 363275
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"363275-1291076438000"
          Last-Modified: Tue, 30 Nov 2010 00:20:38 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (363275 bytes)
          /*!
           * jQuery UI 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI
           */
          (function( $, undefined ) {
          
          // prevent duplicate loading
          // this is only a problem because we proxy existing functions
          // and we don't want to double proxy them
          $.ui = $.ui || {};
          if ( $.ui.version ) {
          	return;
          }
          
          $.extend( $.ui, {
          	version: "1.8.6",
          
          	keyCode: {
          		ALT: 18,
          		BACKSPACE: 8,
          		CAPS_LOCK: 20,
          		COMMA: 188,
          		COMMAND: 91,
          		COMMAND_LEFT: 91, // COMMAND
          		COMMAND_RIGHT: 93,
          		CONTROL: 17,
          		DELETE: 46,
          		DOWN: 40,
          		END: 35,
          		ENTER: 13,
          		ESCAPE: 27,
          		HOME: 36,
          		INSERT: 45,
          		LEFT: 37,
          		MENU: 93, // COMMAND_RIGHT
          		NUMPAD_ADD: 107,
          		NUMPAD_DECIMAL: 110,
          		NUMPAD_DIVIDE: 111,
          		NUMPAD_ENTER: 108,
          		NUMPAD_MULTIPLY: 106,
          		NUMPAD_SUBTRACT: 109,
          		PAGE_DOWN: 34,
          		PAGE_UP: 33,
          		PERIOD: 190,
          		RIGHT: 39,
          		SHIFT: 16,
          		SPACE: 32,
          		TAB: 9,
          		UP: 38,
          		WINDOWS: 91 // COMMAND
          	}
          });
          
          // plugins
          $.fn.extend({
          	_focus: $.fn.focus,
          	focus: function( delay, fn ) {
          		return typeof delay === "number" ?
          			this.each(function() {
          				var elem = this;
          				setTimeout(function() {
          					$( elem ).focus();
          					if ( fn ) {
          						fn.call( elem );
          					}
          				}, delay );
          			}) :
          			this._focus.apply( this, arguments );
          	},
          
          	scrollParent: function() {
          		var scrollParent;
          		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
          			scrollParent = this.parents().filter(function() {
          				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		} else {
          			scrollParent = this.parents().filter(function() {
          				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
          			}).eq(0);
          		}
          
          		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
          	},
          
          	zIndex: function( zIndex ) {
          		if ( zIndex !== undefined ) {
          			return this.css( "zIndex", zIndex );
          		}
          
          		if ( this.length ) {
          			var elem = $( this[ 0 ] ), position, value;
          			while ( elem.length && elem[ 0 ] !== document ) {
          				// Ignore z-index if position is set to a value where z-index is ignored by the browser
          				// This makes behavior of this function consistent across browsers
          				// WebKit always returns auto if the element is positioned
          				position = elem.css( "position" );
          				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
          					// IE returns 0 when zIndex is not specified
          					// other browsers return a string
          					// we ignore the case of nested elements with an explicit value of 0
          					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
          					value = parseInt( elem.css( "zIndex" ), 10 );
          					if ( !isNaN( value ) && value !== 0 ) {
          						return value;
          					}
          				}
          				elem = elem.parent();
          			}
          		}
          
          		return 0;
          	},
          
          	disableSelection: function() {
          		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
          			".ui-disableSelection", function( event ) {
          				event.preventDefault();
          			});
          	},
          
          	enableSelection: function() {
          		return this.unbind( ".ui-disableSelection" );
          	}
          });
          
          $.each( [ "Width", "Height" ], function( i, name ) {
          	var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
          		type = name.toLowerCase(),
          		orig = {
          			innerWidth: $.fn.innerWidth,
          			innerHeight: $.fn.innerHeight,
          			outerWidth: $.fn.outerWidth,
          			outerHeight: $.fn.outerHeight
          		};
          
          	function reduce( elem, size, border, margin ) {
          		$.each( side, function() {
          			size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
          			if ( border ) {
          				size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
          			}
          			if ( margin ) {
          				size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
          			}
          		});
          		return size;
          	}
          
          	$.fn[ "inner" + name ] = function( size ) {
          		if ( size === undefined ) {
          			return orig[ "inner" + name ].call( this );
          		}
          
          		return this.each(function() {
          			$( this ).css( type, reduce( this, size ) + "px" );
          		});
          	};
          
          	$.fn[ "outer" + name] = function( size, margin ) {
          		if ( typeof size !== "number" ) {
          			return orig[ "outer" + name ].call( this, size );
          		}
          
          		return this.each(function() {
          			$( this).css( type, reduce( this, size, true, margin ) + "px" );
          		});
          	};
          });
          
          // selectors
          function visible( element ) {
          	return !$( element ).parents().andSelf().filter(function() {
          		return $.curCSS( this, "visibility" ) === "hidden" ||
          			$.expr.filters.hidden( this );
          	}).length;
          }
          
          $.extend( $.expr[ ":" ], {
          	data: function( elem, i, match ) {
          		return !!$.data( elem, match[ 3 ] );
          	},
          
          	focusable: function( element ) {
          		var nodeName = element.nodeName.toLowerCase(),
          			tabIndex = $.attr( element, "tabindex" );
          		if ( "area" === nodeName ) {
          			var map = element.parentNode,
          				mapName = map.name,
          				img;
          			if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
          				return false;
          			}
          			img = $( "img[usemap=#" + mapName + "]" )[0];
          			return !!img && visible( img );
          		}
          		return ( /input|select|textarea|button|object/.test( nodeName )
          			? !element.disabled
          			: "a" == nodeName
          				? element.href || !isNaN( tabIndex )
          				: !isNaN( tabIndex ))
          			// the element and all of its ancestors must be visible
          			&& visible( element );
          	},
          
          	tabbable: function( element ) {
          		var tabIndex = $.attr( element, "tabindex" );
          		return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
          	}
          });
          
          // support
          $(function() {
          	var body = document.body,
          		div = body.appendChild( div = document.createElement( "div" ) );
          
          	$.extend( div.style, {
          		minHeight: "100px",
          		height: "auto",
          		padding: 0,
          		borderWidth: 0
          	});
          
          	$.support.minHeight = div.offsetHeight === 100;
          	$.support.selectstart = "onselectstart" in div;
          
          	// set display to none to avoid a layout bug in IE
          	// http://dev.jquery.com/ticket/4014
          	body.removeChild( div ).style.display = "none";
          });
          
          
          
          
          
          // deprecated
          $.extend( $.ui, {
          	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
          	plugin: {
          		add: function( module, option, set ) {
          			var proto = $.ui[ module ].prototype;
          			for ( var i in set ) {
          				proto.plugins[ i ] = proto.plugins[ i ] || [];
          				proto.plugins[ i ].push( [ option, set[ i ] ] );
          			}
          		},
          		call: function( instance, name, args ) {
          			var set = instance.plugins[ name ];
          			if ( !set || !instance.element[ 0 ].parentNode ) {
          				return;
          			}
          	
          			for ( var i = 0; i < set.length; i++ ) {
          				if ( instance.options[ set[ i ][ 0 ] ] ) {
          					set[ i ][ 1 ].apply( instance.element, args );
          				}
          			}
          		}
          	},
          	
          	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
          	contains: function( a, b ) {
          		return document.compareDocumentPosition ?
          			a.compareDocumentPosition( b ) & 16 :
          			a !== b && a.contains( b );
          	},
          	
          	// only used by resizable
          	hasScroll: function( el, a ) {
          	
          		//If overflow is hidden, the element might have extra content, but the user wants to hide it
          		if ( $( el ).css( "overflow" ) === "hidden") {
          			return false;
          		}
          	
          		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
          			has = false;
          	
          		if ( el[ scroll ] > 0 ) {
          			return true;
          		}
          	
          		// TODO: determine which cases actually cause this to happen
          		// if the element doesn't have the scroll set, see if it's possible to
          		// set the scroll
          		el[ scroll ] = 1;
          		has = ( el[ scroll ] > 0 );
          		el[ scroll ] = 0;
          		return has;
          	},
          	
          	// these are odd functions, fix the API or move into individual plugins
          	isOverAxis: function( x, reference, size ) {
          		//Determines when x coordinate is over "b" element axis
          		return ( x > reference ) && ( x < ( reference + size ) );
          	},
          	isOver: function( y, x, top, left, height, width ) {
          		//Determines when x, y coordinates is over "b" element
          		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
          	}
          });
          
          })( jQuery );
          /*!
           * jQuery UI Widget 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Widget
           */
          (function( $, undefined ) {
          
          // jQuery 1.4+
          if ( $.cleanData ) {
          	var _cleanData = $.cleanData;
          	$.cleanData = function( elems ) {
          		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
          			$( elem ).triggerHandler( "remove" );
          		}
          		_cleanData( elems );
          	};
          } else {
          	var _remove = $.fn.remove;
          	$.fn.remove = function( selector, keepData ) {
          		return this.each(function() {
          			if ( !keepData ) {
          				if ( !selector || $.filter( selector, [ this ] ).length ) {
          					$( "*", this ).add( [ this ] ).each(function() {
          						$( this ).triggerHandler( "remove" );
          					});
          				}
          			}
          			return _remove.call( $(this), selector, keepData );
          		});
          	};
          }
          
          $.widget = function( name, base, prototype ) {
          	var namespace = name.split( "." )[ 0 ],
          		fullName;
          	name = name.split( "." )[ 1 ];
          	fullName = namespace + "-" + name;
          
          	if ( !prototype ) {
          		prototype = base;
          		base = $.Widget;
          	}
          
          	// create selector for plugin
          	$.expr[ ":" ][ fullName ] = function( elem ) {
          		return !!$.data( elem, name );
          	};
          
          	$[ namespace ] = $[ namespace ] || {};
          	$[ namespace ][ name ] = function( options, element ) {
          		// allow instantiation without initializing for simple inheritance
          		if ( arguments.length ) {
          			this._createWidget( options, element );
          		}
          	};
          
          	var basePrototype = new base();
          	// we need to make the options hash a property directly on the new instance
          	// otherwise we'll modify the options hash on the prototype that we're
          	// inheriting from
          //	$.each( basePrototype, function( key, val ) {
          //		if ( $.isPlainObject(val) ) {
          //			basePrototype[ key ] = $.extend( {}, val );
          //		}
          //	});
          	basePrototype.options = $.extend( true, {}, basePrototype.options );
          	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
          		namespace: namespace,
          		widgetName: name,
          		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
          		widgetBaseClass: fullName
          	}, prototype );
          
          	$.widget.bridge( name, $[ namespace ][ name ] );
          };
          
          $.widget.bridge = function( name, object ) {
          	$.fn[ name ] = function( options ) {
          		var isMethodCall = typeof options === "string",
          			args = Array.prototype.slice.call( arguments, 1 ),
          			returnValue = this;
          
          		// allow multiple hashes to be passed on init
          		options = !isMethodCall && args.length ?
          			$.extend.apply( null, [ true, options ].concat(args) ) :
          			options;
          
          		// prevent calls to internal methods
          		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
          			return returnValue;
          		}
          
          		if ( isMethodCall ) {
          			this.each(function() {
          				var instance = $.data( this, name ),
          					methodValue = instance && $.isFunction( instance[options] ) ?
          						instance[ options ].apply( instance, args ) :
          						instance;
          				// TODO: add this back in 1.9 and use $.error() (see #5972)
          //				if ( !instance ) {
          //					throw "cannot call methods on " + name + " prior to initialization; " +
          //						"attempted to call method '" + options + "'";
          //				}
          //				if ( !$.isFunction( instance[options] ) ) {
          //					throw "no such method '" + options + "' for " + name + " widget instance";
          //				}
          //				var methodValue = instance[ options ].apply( instance, args );
          				if ( methodValue !== instance && methodValue !== undefined ) {
          					returnValue = methodValue;
          					return false;
          				}
          			});
          		} else {
          			this.each(function() {
          				var instance = $.data( this, name );
          				if ( instance ) {
          					instance.option( options || {} )._init();
          				} else {
          					$.data( this, name, new object( options, this ) );
          				}
          			});
          		}
          
          		return returnValue;
          	};
          };
          
          $.Widget = function( options, element ) {
          	// allow instantiation without initializing for simple inheritance
          	if ( arguments.length ) {
          		this._createWidget( options, element );
          	}
          };
          
          $.Widget.prototype = {
          	widgetName: "widget",
          	widgetEventPrefix: "",
          	options: {
          		disabled: false
          	},
          	_createWidget: function( options, element ) {
          		// $.widget.bridge stores the plugin instance, but we do it anyway
          		// so that it's stored even before the _create function runs
          		$.data( element, this.widgetName, this );
          		this.element = $( element );
          		this.options = $.extend( true, {},
          			this.options,
          			this._getCreateOptions(),
          			options );
          
          		var self = this;
          		this.element.bind( "remove." + this.widgetName, function() {
          			self.destroy();
          		});
          
          		this._create();
          		this._trigger( "create" );
          		this._init();
          	},
          	_getCreateOptions: function() {
          		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
          	},
          	_create: function() {},
          	_init: function() {},
          
          	destroy: function() {
          		this.element
          			.unbind( "." + this.widgetName )
          			.removeData( this.widgetName );
          		this.widget()
          			.unbind( "." + this.widgetName )
          			.removeAttr( "aria-disabled" )
          			.removeClass(
          				this.widgetBaseClass + "-disabled " +
          				"ui-state-disabled" );
          	},
          
          	widget: function() {
          		return this.element;
          	},
          
          	option: function( key, value ) {
          		var options = key;
          
          		if ( arguments.length === 0 ) {
          			// don't return a reference to the internal hash
          			return $.extend( {}, this.options );
          		}
          
          		if  (typeof key === "string" ) {
          			if ( value === undefined ) {
          				return this.options[ key ];
          			}
          			options = {};
          			options[ key ] = value;
          		}
          
          		this._setOptions( options );
          
          		return this;
          	},
          	_setOptions: function( options ) {
          		var self = this;
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          		});
          
          		return this;
          	},
          	_setOption: function( key, value ) {
          		this.options[ key ] = value;
          
          		if ( key === "disabled" ) {
          			this.widget()
          				[ value ? "addClass" : "removeClass"](
          					this.widgetBaseClass + "-disabled" + " " +
          					"ui-state-disabled" )
          				.attr( "aria-disabled", value );
          		}
          
          		return this;
          	},
          
          	enable: function() {
          		return this._setOption( "disabled", false );
          	},
          	disable: function() {
          		return this._setOption( "disabled", true );
          	},
          
          	_trigger: function( type, event, data ) {
          		var callback = this.options[ type ];
          
          		event = $.Event( event );
          		event.type = ( type === this.widgetEventPrefix ?
          			type :
          			this.widgetEventPrefix + type ).toLowerCase();
          		data = data || {};
          
          		// copy original event properties over to the new event
          		// this would happen if we could call $.event.fix instead of $.Event
          		// but we don't have a way to force an event to be fixed multiple times
          		if ( event.originalEvent ) {
          			for ( var i = $.event.props.length, prop; i; ) {
          				prop = $.event.props[ --i ];
          				event[ prop ] = event.originalEvent[ prop ];
          			}
          		}
          
          		this.element.trigger( event, data );
          
          		return !( $.isFunction(callback) &&
          			callback.call( this.element[0], event, data ) === false ||
          			event.isDefaultPrevented() );
          	}
          };
          
          })( jQuery );
          /*!
           * jQuery UI Mouse 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Mouse
           *
           * Depends:
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.mouse", {
          	options: {
          		cancel: ':input,option',
          		distance: 1,
          		delay: 0
          	},
          	_mouseInit: function() {
          		var self = this;
          
          		this.element
          			.bind('mousedown.'+this.widgetName, function(event) {
          				return self._mouseDown(event);
          			})
          			.bind('click.'+this.widgetName, function(event) {
          				if(self._preventClickEvent) {
          					self._preventClickEvent = false;
          					event.stopImmediatePropagation();
          					return false;
          				}
          			});
          
          		this.started = false;
          	},
          
          	// TODO: make sure destroying one instance of mouse doesn't mess with
          	// other instances of mouse
          	_mouseDestroy: function() {
          		this.element.unbind('.'+this.widgetName);
          	},
          
          	_mouseDown: function(event) {
          		// don't let more than one widget handle mouseStart
          		// TODO: figure out why we have to use originalEvent
          		event.originalEvent = event.originalEvent || {};
          		if (event.originalEvent.mouseHandled) { return; }
          
          		// we may have missed mouseup (out of window)
          		(this._mouseStarted && this._mouseUp(event));
          
          		this._mouseDownEvent = event;
          
          		var self = this,
          			btnIsLeft = (event.which == 1),
          			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
          		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
          			return true;
          		}
          
          		this.mouseDelayMet = !this.options.delay;
          		if (!this.mouseDelayMet) {
          			this._mouseDelayTimer = setTimeout(function() {
          				self.mouseDelayMet = true;
          			}, this.options.delay);
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted = (this._mouseStart(event) !== false);
          			if (!this._mouseStarted) {
          				event.preventDefault();
          				return true;
          			}
          		}
          
          		// these delegates are required to keep context
          		this._mouseMoveDelegate = function(event) {
          			return self._mouseMove(event);
          		};
          		this._mouseUpDelegate = function(event) {
          			return self._mouseUp(event);
          		};
          		$(document)
          			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		event.preventDefault();
          		event.originalEvent.mouseHandled = true;
          		return true;
          	},
          
          	_mouseMove: function(event) {
          		// IE mouseup check - mouseup happened when mouse was out of window
          		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
          			return this._mouseUp(event);
          		}
          
          		if (this._mouseStarted) {
          			this._mouseDrag(event);
          			return event.preventDefault();
          		}
          
          		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
          			this._mouseStarted =
          				(this._mouseStart(this._mouseDownEvent, event) !== false);
          			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
          		}
          
          		return !this._mouseStarted;
          	},
          
          	_mouseUp: function(event) {
          		$(document)
          			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
          			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
          
          		if (this._mouseStarted) {
          			this._mouseStarted = false;
          			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
          			this._mouseStop(event);
          		}
          
          		return false;
          	},
          
          	_mouseDistanceMet: function(event) {
          		return (Math.max(
          				Math.abs(this._mouseDownEvent.pageX - event.pageX),
          				Math.abs(this._mouseDownEvent.pageY - event.pageY)
          			) >= this.options.distance
          		);
          	},
          
          	_mouseDelayMet: function(event) {
          		return this.mouseDelayMet;
          	},
          
          	// These are placeholder methods, to be overriden by extending plugin
          	_mouseStart: function(event) {},
          	_mouseDrag: function(event) {},
          	_mouseStop: function(event) {},
          	_mouseCapture: function(event) { return true; }
          });
          
          })(jQuery);
          /*
           * jQuery UI Draggable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Draggables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.draggable", $.ui.mouse, {
          	widgetEventPrefix: "drag",
          	options: {
          		addClasses: true,
          		appendTo: "parent",
          		axis: false,
          		connectToSortable: false,
          		containment: false,
          		cursor: "auto",
          		cursorAt: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		iframeFix: false,
          		opacity: false,
          		refreshPositions: false,
          		revert: false,
          		revertDuration: 500,
          		scope: "default",
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		snap: false,
          		snapMode: "both",
          		snapTolerance: 20,
          		stack: false,
          		zIndex: false
          	},
          	_create: function() {
          
          		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
          			this.element[0].style.position = 'relative';
          
          		(this.options.addClasses && this.element.addClass("ui-draggable"));
          		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
          
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		if(!this.element.data('draggable')) return;
          		this.element
          			.removeData("draggable")
          			.unbind(".draggable")
          			.removeClass("ui-draggable"
          				+ " ui-draggable-dragging"
          				+ " ui-draggable-disabled");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          
          		var o = this.options;
          
          		// among others, prevent a drag on a resizable-handle
          		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
          			return false;
          
          		//Quit if we're not on a valid handle
          		this.handle = this._getHandle(event);
          		if (!this.handle)
          			return false;
          
          		return true;
          
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options;
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		//If ddmanager is used for droppables, set the global draggable
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Store the helper's css position
          		this.cssPosition = this.helper.css("position");
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.positionAbs = this.element.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this.position = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		//Trigger event + callbacks
          		if(this._trigger("start", event) === false) {
          			this._clear();
          			return false;
          		}
          
          		//Recache the helper size
          		this._cacheHelperProportions();
          
          		//Prepare the droppable offsets
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.helper.addClass("ui-draggable-dragging");
          		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          	},
          
          	_mouseDrag: function(event, noPropagation) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Call plugins and callbacks and use the resulting position if something is returned
          		if (!noPropagation) {
          			var ui = this._uiHash();
          			if(this._trigger('drag', event, ui) === false) {
          				this._mouseUp({});
          				return false;
          			}
          			this.position = ui.position;
          		}
          
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		//If we are using droppables, inform the manager about the drop
          		var dropped = false;
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			dropped = $.ui.ddmanager.drop(this, event);
          
          		//if a drop comes from outside (a sortable)
          		if(this.dropped) {
          			dropped = this.dropped;
          			this.dropped = false;
          		}
          		
          		//if the original element is removed, don't bother to continue
          		if(!this.element[0] || !this.element[0].parentNode)
          			return false;
          
          		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
          			var self = this;
          			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
          				if(self._trigger("stop", event) !== false) {
          					self._clear();
          				}
          			});
          		} else {
          			if(this._trigger("stop", event) !== false) {
          				this._clear();
          			}
          		}
          
          		return false;
          	},
          	
          	cancel: function() {
          		
          		if(this.helper.is(".ui-draggable-dragging")) {
          			this._mouseUp({});
          		} else {
          			this._clear();
          		}
          		
          		return this;
          		
          	},
          
          	_getHandle: function(event) {
          
          		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
          		$(this.options.handle, this.element)
          			.find("*")
          			.andSelf()
          			.each(function() {
          				if(this == event.target) handle = true;
          			});
          
          		return handle;
          
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
          
          		if(!helper.parents('body').length)
          			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
          
          		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
          			helper.css("position", "absolute");
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.element.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.element.css("marginLeft"),10) || 0),
          			top: (parseInt(this.element.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
          			var ce = $(o.containment)[0]; if(!ce) return;
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		} else if(o.containment.constructor == Array) {
          			this.containment = o.containment;
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_clear: function() {
          		this.helper.removeClass("ui-draggable-dragging");
          		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
          		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
          		this.helper = null;
          		this.cancelHelperRemoval = false;
          	},
          
          	// From now on bulk stuff - mainly helpers
          
          	_trigger: function(type, event, ui) {
          		ui = ui || this._uiHash();
          		$.ui.plugin.call(this, type, [event, ui]);
          		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
          		return $.Widget.prototype._trigger.call(this, type, event, ui);
          	},
          
          	plugins: {},
          
          	_uiHash: function(event) {
          		return {
          			helper: this.helper,
          			position: this.position,
          			originalPosition: this.originalPosition,
          			offset: this.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.draggable, {
          	version: "1.8.6"
          });
          
          $.ui.plugin.add("draggable", "connectToSortable", {
          	start: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options,
          			uiSortable = $.extend({}, ui, { item: inst.element });
          		inst.sortables = [];
          		$(o.connectToSortable).each(function() {
          			var sortable = $.data(this, 'sortable');
          			if (sortable && !sortable.options.disabled) {
          				inst.sortables.push({
          					instance: sortable,
          					shouldRevert: sortable.options.revert
          				});
          				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
          				sortable._trigger("activate", event, uiSortable);
          			}
          		});
          
          	},
          	stop: function(event, ui) {
          
          		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
          		var inst = $(this).data("draggable"),
          			uiSortable = $.extend({}, ui, { item: inst.element });
          
          		$.each(inst.sortables, function() {
          			if(this.instance.isOver) {
          
          				this.instance.isOver = 0;
          
          				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
          				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
          
          				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
          				if(this.shouldRevert) this.instance.options.revert = true;
          
          				//Trigger the stop of the sortable
          				this.instance._mouseStop(event);
          
          				this.instance.options.helper = this.instance.options._helper;
          
          				//If the helper has been the original item, restore properties in the sortable
          				if(inst.options.helper == 'original')
          					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
          
          			} else {
          				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
          				this.instance._trigger("deactivate", event, uiSortable);
          			}
          
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), self = this;
          
          		var checkPos = function(o) {
          			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
          			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
          			var itemHeight = o.height, itemWidth = o.width;
          			var itemTop = o.top, itemLeft = o.left;
          
          			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
          		};
          
          		$.each(inst.sortables, function(i) {
          			
          			//Copy over some variables to allow calling the sortable's native _intersectsWith
          			this.instance.positionAbs = inst.positionAbs;
          			this.instance.helperProportions = inst.helperProportions;
          			this.instance.offset.click = inst.offset.click;
          			
          			if(this.instance._intersectsWith(this.instance.containerCache)) {
          
          				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
          				if(!this.instance.isOver) {
          
          					this.instance.isOver = 1;
          					//Now we fake the start of dragging for the sortable instance,
          					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
          					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
          					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
          					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
          					this.instance.options.helper = function() { return ui.helper[0]; };
          
          					event.target = this.instance.currentItem[0];
          					this.instance._mouseCapture(event, true);
          					this.instance._mouseStart(event, true, true);
          
          					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
          					this.instance.offset.click.top = inst.offset.click.top;
          					this.instance.offset.click.left = inst.offset.click.left;
          					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
          					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
          
          					inst._trigger("toSortable", event);
          					inst.dropped = this.instance.element; //draggable revert needs that
          					//hack so receive/update callbacks work (mostly)
          					inst.currentItem = inst.element;
          					this.instance.fromOutside = inst;
          
          				}
          
          				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
          				if(this.instance.currentItem) this.instance._mouseDrag(event);
          
          			} else {
          
          				//If it doesn't intersect with the sortable, and it intersected before,
          				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
          				if(this.instance.isOver) {
          
          					this.instance.isOver = 0;
          					this.instance.cancelHelperRemoval = true;
          					
          					//Prevent reverting on this forced stop
          					this.instance.options.revert = false;
          					
          					// The out event needs to be triggered independently
          					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
          					
          					this.instance._mouseStop(event, true);
          					this.instance.options.helper = this.instance.options._helper;
          
          					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
          					this.instance.currentItem.remove();
          					if(this.instance.placeholder) this.instance.placeholder.remove();
          
          					inst._trigger("fromSortable", event);
          					inst.dropped = false; //draggable revert needs that
          				}
          
          			};
          
          		});
          
          	}
          });
          
          $.ui.plugin.add("draggable", "cursor", {
          	start: function(event, ui) {
          		var t = $('body'), o = $(this).data('draggable').options;
          		if (t.css("cursor")) o._cursor = t.css("cursor");
          		t.css("cursor", o.cursor);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if (o._cursor) $('body').css("cursor", o._cursor);
          	}
          });
          
          $.ui.plugin.add("draggable", "iframeFix", {
          	start: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
          			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
          			.css({
          				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
          				position: "absolute", opacity: "0.001", zIndex: 1000
          			})
          			.css($(this).offset())
          			.appendTo("body");
          		});
          	},
          	stop: function(event, ui) {
          		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
          	}
          });
          
          $.ui.plugin.add("draggable", "opacity", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data('draggable').options;
          		if(t.css("opacity")) o._opacity = t.css("opacity");
          		t.css('opacity', o.opacity);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data('draggable').options;
          		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
          	}
          });
          
          $.ui.plugin.add("draggable", "scroll", {
          	start: function(event, ui) {
          		var i = $(this).data("draggable");
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
          	},
          	drag: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options, scrolled = false;
          
          		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
          
          			if(!o.axis || o.axis != 'x') {
          				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
          					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
          					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
          			}
          
          		} else {
          
          			if(!o.axis || o.axis != 'x') {
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          			}
          
          			if(!o.axis || o.axis != 'y') {
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          			}
          
          		}
          
          		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(i, event);
          
          	}
          });
          
          $.ui.plugin.add("draggable", "snap", {
          	start: function(event, ui) {
          
          		var i = $(this).data("draggable"), o = i.options;
          		i.snapElements = [];
          
          		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
          			var $t = $(this); var $o = $t.offset();
          			if(this != i.element[0]) i.snapElements.push({
          				item: this,
          				width: $t.outerWidth(), height: $t.outerHeight(),
          				top: $o.top, left: $o.left
          			});
          		});
          
          	},
          	drag: function(event, ui) {
          
          		var inst = $(this).data("draggable"), o = inst.options;
          		var d = o.snapTolerance;
          
          		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
          			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
          
          		for (var i = inst.snapElements.length - 1; i >= 0; i--){
          
          			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
          				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
          
          			//Yes, I know, this is insane ;)
          			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
          				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          				inst.snapElements[i].snapping = false;
          				continue;
          			}
          
          			if(o.snapMode != 'inner') {
          				var ts = Math.abs(t - y2) <= d;
          				var bs = Math.abs(b - y1) <= d;
          				var ls = Math.abs(l - x2) <= d;
          				var rs = Math.abs(r - x1) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
          			}
          
          			var first = (ts || bs || ls || rs);
          
          			if(o.snapMode != 'outer') {
          				var ts = Math.abs(t - y1) <= d;
          				var bs = Math.abs(b - y2) <= d;
          				var ls = Math.abs(l - x1) <= d;
          				var rs = Math.abs(r - x2) <= d;
          				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
          				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
          				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
          				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
          			}
          
          			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
          				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
          			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
          
          		};
          
          	}
          });
          
          $.ui.plugin.add("draggable", "stack", {
          	start: function(event, ui) {
          
          		var o = $(this).data("draggable").options;
          
          		var group = $.makeArray($(o.stack)).sort(function(a,b) {
          			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
          		});
          		if (!group.length) { return; }
          		
          		var min = parseInt(group[0].style.zIndex) || 0;
          		$(group).each(function(i) {
          			this.style.zIndex = min + i;
          		});
          
          		this[0].style.zIndex = min + group.length;
          
          	}
          });
          
          $.ui.plugin.add("draggable", "zIndex", {
          	start: function(event, ui) {
          		var t = $(ui.helper), o = $(this).data("draggable").options;
          		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
          		t.css('zIndex', o.zIndex);
          	},
          	stop: function(event, ui) {
          		var o = $(this).data("draggable").options;
          		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
          	}
          });
          
          })(jQuery);
          /*
           * jQuery UI Droppable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Droppables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.mouse.js
           *	jquery.ui.draggable.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.droppable", {
          	widgetEventPrefix: "drop",
          	options: {
          		accept: '*',
          		activeClass: false,
          		addClasses: true,
          		greedy: false,
          		hoverClass: false,
          		scope: 'default',
          		tolerance: 'intersect'
          	},
          	_create: function() {
          
          		var o = this.options, accept = o.accept;
          		this.isover = 0; this.isout = 1;
          
          		this.accept = $.isFunction(accept) ? accept : function(d) {
          			return d.is(accept);
          		};
          
          		//Store the droppable's proportions
          		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
          
          		// Add the reference and positions to the manager
          		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
          		$.ui.ddmanager.droppables[o.scope].push(this);
          
          		(o.addClasses && this.element.addClass("ui-droppable"));
          
          	},
          
          	destroy: function() {
          		var drop = $.ui.ddmanager.droppables[this.options.scope];
          		for ( var i = 0; i < drop.length; i++ )
          			if ( drop[i] == this )
          				drop.splice(i, 1);
          
          		this.element
          			.removeClass("ui-droppable ui-droppable-disabled")
          			.removeData("droppable")
          			.unbind(".droppable");
          
          		return this;
          	},
          
          	_setOption: function(key, value) {
          
          		if(key == 'accept') {
          			this.accept = $.isFunction(value) ? value : function(d) {
          				return d.is(value);
          			};
          		}
          		$.Widget.prototype._setOption.apply(this, arguments);
          	},
          
          	_activate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
          		(draggable && this._trigger('activate', event, this.ui(draggable)));
          	},
          
          	_deactivate: function(event) {
          		var draggable = $.ui.ddmanager.current;
          		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
          	},
          
          	_over: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
          			this._trigger('over', event, this.ui(draggable));
          		}
          
          	},
          
          	_out: function(event) {
          
          		var draggable = $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
          
          		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('out', event, this.ui(draggable));
          		}
          
          	},
          
          	_drop: function(event,custom) {
          
          		var draggable = custom || $.ui.ddmanager.current;
          		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
          
          		var childrenIntersection = false;
          		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
          			var inst = $.data(this, 'droppable');
          			if(
          				inst.options.greedy
          				&& !inst.options.disabled
          				&& inst.options.scope == draggable.options.scope
          				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
          				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
          			) { childrenIntersection = true; return false; }
          		});
          		if(childrenIntersection) return false;
          
          		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
          			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
          			this._trigger('drop', event, this.ui(draggable));
          			return this.element;
          		}
          
          		return false;
          
          	},
          
          	ui: function(c) {
          		return {
          			draggable: (c.currentItem || c.element),
          			helper: c.helper,
          			position: c.position,
          			offset: c.positionAbs
          		};
          	}
          
          });
          
          $.extend($.ui.droppable, {
          	version: "1.8.6"
          });
          
          $.ui.intersect = function(draggable, droppable, toleranceMode) {
          
          	if (!droppable.offset) return false;
          
          	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
          		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
          	var l = droppable.offset.left, r = l + droppable.proportions.width,
          		t = droppable.offset.top, b = t + droppable.proportions.height;
          
          	switch (toleranceMode) {
          		case 'fit':
          			return (l <= x1 && x2 <= r
          				&& t <= y1 && y2 <= b);
          			break;
          		case 'intersect':
          			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
          				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
          				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
          			break;
          		case 'pointer':
          			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
          				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
          				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
          			return isOver;
          			break;
          		case 'touch':
          			return (
          					(y1 >= t && y1 <= b) ||	// Top edge touching
          					(y2 >= t && y2 <= b) ||	// Bottom edge touching
          					(y1 < t && y2 > b)		// Surrounded vertically
          				) && (
          					(x1 >= l && x1 <= r) ||	// Left edge touching
          					(x2 >= l && x2 <= r) ||	// Right edge touching
          					(x1 < l && x2 > r)		// Surrounded horizontally
          				);
          			break;
          		default:
          			return false;
          			break;
          		}
          
          };
          
          /*
          	This manager tracks offsets of draggables and droppables
          */
          $.ui.ddmanager = {
          	current: null,
          	droppables: { 'default': [] },
          	prepareOffsets: function(t, event) {
          
          		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
          		var type = event ? event.type : null; // workaround for #2317
          		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
          
          		droppablesLoop: for (var i = 0; i < m.length; i++) {
          
          			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
          			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
          			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
          
          			m[i].offset = m[i].element.offset();
          			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
          
          			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
          
          		}
          
          	},
          	drop: function(draggable, event) {
          
          		var dropped = false;
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(!this.options) return;
          			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
          				dropped = dropped || this._drop.call(this, event);
          
          			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
          				this.isout = 1; this.isover = 0;
          				this._deactivate.call(this, event);
          			}
          
          		});
          		return dropped;
          
          	},
          	drag: function(draggable, event) {
          
          		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
          		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
          
          		//Run through all droppables and check their positions based on specific tolerance options
          		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
          
          			if(this.options.disabled || this.greedyChild || !this.visible) return;
          			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
          
          			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
          			if(!c) return;
          
          			var parentInstance;
          			if (this.options.greedy) {
          				var parent = this.element.parents(':data(droppable):eq(0)');
          				if (parent.length) {
          					parentInstance = $.data(parent[0], 'droppable');
          					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
          				}
          			}
          
          			// we just moved into a greedy child
          			if (parentInstance && c == 'isover') {
          				parentInstance['isover'] = 0;
          				parentInstance['isout'] = 1;
          				parentInstance._out.call(parentInstance, event);
          			}
          
          			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
          			this[c == "isover" ? "_over" : "_out"].call(this, event);
          
          			// we just moved out of a greedy child
          			if (parentInstance && c == 'isout') {
          				parentInstance['isout'] = 0;
          				parentInstance['isover'] = 1;
          				parentInstance._over.call(parentInstance, event);
          			}
          		});
          
          	}
          };
          
          })(jQuery);
          /*
           * jQuery UI Resizable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Resizables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.resizable", $.ui.mouse, {
          	widgetEventPrefix: "resize",
          	options: {
          		alsoResize: false,
          		animate: false,
          		animateDuration: "slow",
          		animateEasing: "swing",
          		aspectRatio: false,
          		autoHide: false,
          		containment: false,
          		ghost: false,
          		grid: false,
          		handles: "e,s,se",
          		helper: false,
          		maxHeight: null,
          		maxWidth: null,
          		minHeight: 10,
          		minWidth: 10,
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var self = this, o = this.options;
          		this.element.addClass("ui-resizable");
          
          		$.extend(this, {
          			_aspectRatio: !!(o.aspectRatio),
          			aspectRatio: o.aspectRatio,
          			originalElement: this.element,
          			_proportionallyResizeElements: [],
          			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
          		});
          
          		//Wrap the element if it cannot hold child nodes
          		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
          
          			//Opera fix for relative positioning
          			if (/relative/.test(this.element.css('position')) && $.browser.opera)
          				this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          			//Create a wrapper element and set the wrapper to the new current internal element
          			this.element.wrap(
          				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
          					position: this.element.css('position'),
          					width: this.element.outerWidth(),
          					height: this.element.outerHeight(),
          					top: this.element.css('top'),
          					left: this.element.css('left')
          				})
          			);
          
          			//Overwrite the original this.element
          			this.element = this.element.parent().data(
          				"resizable", this.element.data('resizable')
          			);
          
          			this.elementIsWrapper = true;
          
          			//Move margins to the wrapper
          			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
          			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
          
          			//Prevent Safari textarea resize
          			this.originalResizeStyle = this.originalElement.css('resize');
          			this.originalElement.css('resize', 'none');
          
          			//Push the actual element to our proportionallyResize internal array
          			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
          
          			// avoid IE jump (hard set the margin)
          			this.originalElement.css({ margin: this.originalElement.css('margin') });
          
          			// fix handlers offset
          			this._proportionallyResize();
          
          		}
          
          		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
          		if(this.handles.constructor == String) {
          
          			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
          			var n = this.handles.split(","); this.handles = {};
          
          			for(var i = 0; i < n.length; i++) {
          
          				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
          				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
          
          				// increase zIndex of sw, se, ne, nw axis
          				//TODO : this modifies original option
          				if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
          
          				//TODO : What's going on here?
          				if ('se' == handle) {
          					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
          				};
          
          				//Insert into internal handles object and append to element
          				this.handles[handle] = '.ui-resizable-'+handle;
          				this.element.append(axis);
          			}
          
          		}
          
          		this._renderAxis = function(target) {
          
          			target = target || this.element;
          
          			for(var i in this.handles) {
          
          				if(this.handles[i].constructor == String)
          					this.handles[i] = $(this.handles[i], this.element).show();
          
          				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
          				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
          
          					var axis = $(this.handles[i], this.element), padWrapper = 0;
          
          					//Checking the correct pad and border
          					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
          
          					//The padding type i have to apply...
          					var padPos = [ 'padding',
          						/ne|nw|n/.test(i) ? 'Top' :
          						/se|sw|s/.test(i) ? 'Bottom' :
          						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
          
          					target.css(padPos, padWrapper);
          
          					this._proportionallyResize();
          
          				}
          
          				//TODO: What's that good for? There's not anything to be executed left
          				if(!$(this.handles[i]).length)
          					continue;
          
          			}
          		};
          
          		//TODO: make renderAxis a prototype function
          		this._renderAxis(this.element);
          
          		this._handles = $('.ui-resizable-handle', this.element)
          			.disableSelection();
          
          		//Matching axis name
          		this._handles.mouseover(function() {
          			if (!self.resizing) {
          				if (this.className)
          					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
          				//Axis, default = se
          				self.axis = axis && axis[1] ? axis[1] : 'se';
          			}
          		});
          
          		//If we want to auto hide the elements
          		if (o.autoHide) {
          			this._handles.hide();
          			$(this.element)
          				.addClass("ui-resizable-autohide")
          				.hover(function() {
          					$(this).removeClass("ui-resizable-autohide");
          					self._handles.show();
          				},
          				function(){
          					if (!self.resizing) {
          						$(this).addClass("ui-resizable-autohide");
          						self._handles.hide();
          					}
          				});
          		}
          
          		//Initialize the mouse interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          
          		this._mouseDestroy();
          
          		var _destroy = function(exp) {
          			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
          				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
          		};
          
          		//TODO: Unwrap at same DOM position
          		if (this.elementIsWrapper) {
          			_destroy(this.element);
          			var wrapper = this.element;
          			wrapper.after(
          				this.originalElement.css({
          					position: wrapper.css('position'),
          					width: wrapper.outerWidth(),
          					height: wrapper.outerHeight(),
          					top: wrapper.css('top'),
          					left: wrapper.css('left')
          				})
          			).remove();
          		}
          
          		this.originalElement.css('resize', this.originalResizeStyle);
          		_destroy(this.originalElement);
          
          		return this;
          	},
          
          	_mouseCapture: function(event) {
          		var handle = false;
          		for (var i in this.handles) {
          			if ($(this.handles[i])[0] == event.target) {
          				handle = true;
          			}
          		}
          
          		return !this.options.disabled && handle;
          	},
          
          	_mouseStart: function(event) {
          
          		var o = this.options, iniPos = this.element.position(), el = this.element;
          
          		this.resizing = true;
          		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
          
          		// bugfix for http://dev.jquery.com/ticket/1749
          		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
          			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
          		}
          
          		//Opera fixing relative position
          		if ($.browser.opera && (/relative/).test(el.css('position')))
          			el.css({ position: 'relative', top: 'auto', left: 'auto' });
          
          		this._renderProxy();
          
          		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
          
          		if (o.containment) {
          			curleft += $(o.containment).scrollLeft() || 0;
          			curtop += $(o.containment).scrollTop() || 0;
          		}
          
          		//Store needed variables
          		this.offset = this.helper.offset();
          		this.position = { left: curleft, top: curtop };
          		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
          		this.originalPosition = { left: curleft, top: curtop };
          		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
          		this.originalMousePosition = { left: event.pageX, top: event.pageY };
          
          		//Aspect Ratio
          		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
          
          	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
          	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
          
          		el.addClass("ui-resizable-resizing");
          		this._propagate("start", event);
          		return true;
          	},
          
          	_mouseDrag: function(event) {
          
          		//Increase performance, avoid regex
          		var el = this.helper, o = this.options, props = {},
          			self = this, smp = this.originalMousePosition, a = this.axis;
          
          		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
          		var trigger = this._change[a];
          		if (!trigger) return false;
          
          		// Calculate the attrs that will be change
          		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
          
          		if (this._aspectRatio || event.shiftKey)
          			data = this._updateRatio(data, event);
          
          		data = this._respectSize(data, event);
          
          		// plugins callbacks need to be called first
          		this._propagate("resize", event);
          
          		el.css({
          			top: this.position.top + "px", left: this.position.left + "px",
          			width: this.size.width + "px", height: this.size.height + "px"
          		});
          
          		if (!this._helper && this._proportionallyResizeElements.length)
          			this._proportionallyResize();
          
          		this._updateCache(data);
          
          		// calling the user callback at the end
          		this._trigger('resize', event, this.ui());
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          
          		this.resizing = false;
          		var o = this.options, self = this;
          
          		if(this._helper) {
          			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          						soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          							soffsetw = ista ? 0 : self.sizeDiff.width;
          
          			var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          			if (!o.animate)
          				this.element.css($.extend(s, { top: top, left: left }));
          
          			self.helper.height(self.size.height);
          			self.helper.width(self.size.width);
          
          			if (this._helper && !o.animate) this._proportionallyResize();
          		}
          
          		$('body').css('cursor', 'auto');
          
          		this.element.removeClass("ui-resizable-resizing");
          
          		this._propagate("stop", event);
          
          		if (this._helper) this.helper.remove();
          		return false;
          
          	},
          
          	_updateCache: function(data) {
          		var o = this.options;
          		this.offset = this.helper.offset();
          		if (isNumber(data.left)) this.position.left = data.left;
          		if (isNumber(data.top)) this.position.top = data.top;
          		if (isNumber(data.height)) this.size.height = data.height;
          		if (isNumber(data.width)) this.size.width = data.width;
          	},
          
          	_updateRatio: function(data, event) {
          
          		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
          
          		if (data.height) data.width = (csize.height * this.aspectRatio);
          		else if (data.width) data.height = (csize.width / this.aspectRatio);
          
          		if (a == 'sw') {
          			data.left = cpos.left + (csize.width - data.width);
          			data.top = null;
          		}
          		if (a == 'nw') {
          			data.top = cpos.top + (csize.height - data.height);
          			data.left = cpos.left + (csize.width - data.width);
          		}
          
          		return data;
          	},
          
          	_respectSize: function(data, event) {
          
          		var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
          				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
          					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
          
          		if (isminw) data.width = o.minWidth;
          		if (isminh) data.height = o.minHeight;
          		if (ismaxw) data.width = o.maxWidth;
          		if (ismaxh) data.height = o.maxHeight;
          
          		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
          		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
          
          		if (isminw && cw) data.left = dw - o.minWidth;
          		if (ismaxw && cw) data.left = dw - o.maxWidth;
          		if (isminh && ch)	data.top = dh - o.minHeight;
          		if (ismaxh && ch)	data.top = dh - o.maxHeight;
          
          		// fixing jump error on top/left - bug #2330
          		var isNotwh = !data.width && !data.height;
          		if (isNotwh && !data.left && data.top) data.top = null;
          		else if (isNotwh && !data.top && data.left) data.left = null;
          
          		return data;
          	},
          
          	_proportionallyResize: function() {
          
          		var o = this.options;
          		if (!this._proportionallyResizeElements.length) return;
          		var element = this.helper || this.element;
          
          		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
          
          			var prel = this._proportionallyResizeElements[i];
          
          			if (!this.borderDif) {
          				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
          					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
          
          				this.borderDif = $.map(b, function(v, i) {
          					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
          					return border + padding;
          				});
          			}
          
          			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
          				continue;
          
          			prel.css({
          				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
          				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
          			});
          
          		};
          
          	},
          
          	_renderProxy: function() {
          
          		var el = this.element, o = this.options;
          		this.elementOffset = el.offset();
          
          		if(this._helper) {
          
          			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
          
          			// fix ie6 offset TODO: This seems broken
          			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
          			pxyoffset = ( ie6 ? 2 : -1 );
          
          			this.helper.addClass(this._helper).css({
          				width: this.element.outerWidth() + pxyoffset,
          				height: this.element.outerHeight() + pxyoffset,
          				position: 'absolute',
          				left: this.elementOffset.left - ie6offset +'px',
          				top: this.elementOffset.top - ie6offset +'px',
          				zIndex: ++o.zIndex //TODO: Don't modify option
          			});
          
          			this.helper
          				.appendTo("body")
          				.disableSelection();
          
          		} else {
          			this.helper = this.element;
          		}
          
          	},
          
          	_change: {
          		e: function(event, dx, dy) {
          			return { width: this.originalSize.width + dx };
          		},
          		w: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { left: sp.left + dx, width: cs.width - dx };
          		},
          		n: function(event, dx, dy) {
          			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
          			return { top: sp.top + dy, height: cs.height - dy };
          		},
          		s: function(event, dx, dy) {
          			return { height: this.originalSize.height + dy };
          		},
          		se: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		sw: function(event, dx, dy) {
          			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		},
          		ne: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
          		},
          		nw: function(event, dx, dy) {
          			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
          		}
          	},
          
          	_propagate: function(n, event) {
          		$.ui.plugin.call(this, n, [event, this.ui()]);
          		(n != "resize" && this._trigger(n, event, this.ui()));
          	},
          
          	plugins: {},
          
          	ui: function() {
          		return {
          			originalElement: this.originalElement,
          			element: this.element,
          			helper: this.helper,
          			position: this.position,
          			size: this.size,
          			originalSize: this.originalSize,
          			originalPosition: this.originalPosition
          		};
          	}
          
          });
          
          $.extend($.ui.resizable, {
          	version: "1.8.6"
          });
          
          /*
           * Resizable Extensions
           */
          
          $.ui.plugin.add("resizable", "alsoResize", {
          
          	start: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _store = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				el.data("resizable-alsoresize", {
          					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
          					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
          					position: el.css('position') // to reset Opera on stop()
          				});
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
          			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
          			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
          		}else{
          			_store(o.alsoResize);
          		}
          	},
          
          	resize: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
          
          		var delta = {
          			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
          			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
          		},
          
          		_alsoResize = function (exp, c) {
          			$(exp).each(function() {
          				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
          					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
          
          				$.each(css, function (i, prop) {
          					var sum = (start[prop]||0) + (delta[prop]||0);
          					if (sum && sum >= 0)
          						style[prop] = sum || null;
          				});
          
          				// Opera fixing relative position
          				if ($.browser.opera && /relative/.test(el.css('position'))) {
          					self._revertToRelativePosition = true;
          					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
          				}
          
          				el.css(style);
          			});
          		};
          
          		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
          		}else{
          			_alsoResize(o.alsoResize);
          		}
          	},
          
          	stop: function (event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var _reset = function (exp) {
          			$(exp).each(function() {
          				var el = $(this);
          				// reset position for Opera - no need to verify it was changed
          				el.css({ position: el.data("resizable-alsoresize").position });
          			});
          		};
          
          		if (self._revertToRelativePosition) {
          			self._revertToRelativePosition = false;
          			if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
          				$.each(o.alsoResize, function (exp) { _reset(exp); });
          			}else{
          				_reset(o.alsoResize);
          			}
          		}
          
          		$(this).removeData("resizable-alsoresize");
          	}
          });
          
          $.ui.plugin.add("resizable", "animate", {
          
          	stop: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options;
          
          		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
          					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
          						soffsetw = ista ? 0 : self.sizeDiff.width;
          
          		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
          					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
          						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
          
          		self.element.animate(
          			$.extend(style, top && left ? { top: top, left: left } : {}), {
          				duration: o.animateDuration,
          				easing: o.animateEasing,
          				step: function() {
          
          					var data = {
          						width: parseInt(self.element.css('width'), 10),
          						height: parseInt(self.element.css('height'), 10),
          						top: parseInt(self.element.css('top'), 10),
          						left: parseInt(self.element.css('left'), 10)
          					};
          
          					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
          
          					// propagating resize, and updating values for each animation step
          					self._updateCache(data);
          					self._propagate("resize", event);
          
          				}
          			}
          		);
          	}
          
          });
          
          $.ui.plugin.add("resizable", "containment", {
          
          	start: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, el = self.element;
          		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
          		if (!ce) return;
          
          		self.containerElement = $(ce);
          
          		if (/document/.test(oc) || oc == document) {
          			self.containerOffset = { left: 0, top: 0 };
          			self.containerPosition = { left: 0, top: 0 };
          
          			self.parentData = {
          				element: $(document), left: 0, top: 0,
          				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
          			};
          		}
          
          		// i'm a node, so compute top, left, right, bottom
          		else {
          			var element = $(ce), p = [];
          			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
          
          			self.containerOffset = element.offset();
          			self.containerPosition = element.position();
          			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
          
          			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
          						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
          
          			self.parentData = {
          				element: ce, left: co.left, top: co.top, width: width, height: height
          			};
          		}
          	},
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options,
          				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
          				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
          
          		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
          
          		if (cp.left < (self._helper ? co.left : 0)) {
          			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
          			if (pRatio) self.size.height = self.size.width / o.aspectRatio;
          			self.position.left = o.helper ? co.left : 0;
          		}
          
          		if (cp.top < (self._helper ? co.top : 0)) {
          			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
          			if (pRatio) self.size.width = self.size.height * o.aspectRatio;
          			self.position.top = self._helper ? co.top : 0;
          		}
          
          		self.offset.left = self.parentData.left+self.position.left;
          		self.offset.top = self.parentData.top+self.position.top;
          
          		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
          					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
          
          		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
          		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
          
          		if(isParent && isOffsetRelative) woset -= self.parentData.left;
          
          		if (woset + self.size.width >= self.parentData.width) {
          			self.size.width = self.parentData.width - woset;
          			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
          		}
          
          		if (hoset + self.size.height >= self.parentData.height) {
          			self.size.height = self.parentData.height - hoset;
          			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
          		}
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options, cp = self.position,
          				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
          
          		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
          
          		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
          			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
          
          	}
          });
          
          $.ui.plugin.add("resizable", "ghost", {
          
          	start: function(event, ui) {
          
          		var self = $(this).data("resizable"), o = self.options, cs = self.size;
          
          		self.ghost = self.originalElement.clone();
          		self.ghost
          			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
          			.addClass('ui-resizable-ghost')
          			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
          
          		self.ghost.appendTo(self.helper);
          
          	},
          
          	resize: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
          	},
          
          	stop: function(event, ui){
          		var self = $(this).data("resizable"), o = self.options;
          		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
          	}
          
          });
          
          $.ui.plugin.add("resizable", "grid", {
          
          	resize: function(event, ui) {
          		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
          		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
          		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
          
          		if (/^(se|s|e)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          		}
          		else if (/^(ne)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          		}
          		else if (/^(sw)$/.test(a)) {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.left = op.left - ox;
          		}
          		else {
          			self.size.width = os.width + ox;
          			self.size.height = os.height + oy;
          			self.position.top = op.top - oy;
          			self.position.left = op.left - ox;
          		}
          	}
          
          });
          
          var num = function(v) {
          	return parseInt(v, 10) || 0;
          };
          
          var isNumber = function(value) {
          	return !isNaN(parseInt(value, 10));
          };
          
          })(jQuery);
          /*
           * jQuery UI Selectable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Selectables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.selectable", $.ui.mouse, {
          	options: {
          		appendTo: 'body',
          		autoRefresh: true,
          		distance: 0,
          		filter: '*',
          		tolerance: 'touch'
          	},
          	_create: function() {
          		var self = this;
          
          		this.element.addClass("ui-selectable");
          
          		this.dragged = false;
          
          		// cache selectee children based on filter
          		var selectees;
          		this.refresh = function() {
          			selectees = $(self.options.filter, self.element[0]);
          			selectees.each(function() {
          				var $this = $(this);
          				var pos = $this.offset();
          				$.data(this, "selectable-item", {
          					element: this,
          					$element: $this,
          					left: pos.left,
          					top: pos.top,
          					right: pos.left + $this.outerWidth(),
          					bottom: pos.top + $this.outerHeight(),
          					startselected: false,
          					selected: $this.hasClass('ui-selected'),
          					selecting: $this.hasClass('ui-selecting'),
          					unselecting: $this.hasClass('ui-unselecting')
          				});
          			});
          		};
          		this.refresh();
          
          		this.selectees = selectees.addClass("ui-selectee");
          
          		this._mouseInit();
          
          		this.helper = $("<div class='ui-selectable-helper'></div>");
          	},
          
          	destroy: function() {
          		this.selectees
          			.removeClass("ui-selectee")
          			.removeData("selectable-item");
          		this.element
          			.removeClass("ui-selectable ui-selectable-disabled")
          			.removeData("selectable")
          			.unbind(".selectable");
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseStart: function(event) {
          		var self = this;
          
          		this.opos = [event.pageX, event.pageY];
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		this.selectees = $(options.filter, this.element[0]);
          
          		this._trigger("start", event);
          
          		$(options.appendTo).append(this.helper);
          		// position helper (lasso)
          		this.helper.css({
          			"left": event.clientX,
          			"top": event.clientY,
          			"width": 0,
          			"height": 0
          		});
          
          		if (options.autoRefresh) {
          			this.refresh();
          		}
          
          		this.selectees.filter('.ui-selected').each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.startselected = true;
          			if (!event.metaKey) {
          				selectee.$element.removeClass('ui-selected');
          				selectee.selected = false;
          				selectee.$element.addClass('ui-unselecting');
          				selectee.unselecting = true;
          				// selectable UNSELECTING callback
          				self._trigger("unselecting", event, {
          					unselecting: selectee.element
          				});
          			}
          		});
          
          		$(event.target).parents().andSelf().each(function() {
          			var selectee = $.data(this, "selectable-item");
          			if (selectee) {
          				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
          				selectee.$element
          					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
          					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
          				selectee.unselecting = !doSelect;
          				selectee.selecting = doSelect;
          				selectee.selected = doSelect;
          				// selectable (UN)SELECTING callback
          				if (doSelect) {
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				} else {
          					self._trigger("unselecting", event, {
          						unselecting: selectee.element
          					});
          				}
          				return false;
          			}
          		});
          
          	},
          
          	_mouseDrag: function(event) {
          		var self = this;
          		this.dragged = true;
          
          		if (this.options.disabled)
          			return;
          
          		var options = this.options;
          
          		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
          		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
          		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
          		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
          
          		this.selectees.each(function() {
          			var selectee = $.data(this, "selectable-item");
          			//prevent helper from being selected if appendTo: selectable
          			if (!selectee || selectee.element == self.element[0])
          				return;
          			var hit = false;
          			if (options.tolerance == 'touch') {
          				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
          			} else if (options.tolerance == 'fit') {
          				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
          			}
          
          			if (hit) {
          				// SELECT
          				if (selectee.selected) {
          					selectee.$element.removeClass('ui-selected');
          					selectee.selected = false;
          				}
          				if (selectee.unselecting) {
          					selectee.$element.removeClass('ui-unselecting');
          					selectee.unselecting = false;
          				}
          				if (!selectee.selecting) {
          					selectee.$element.addClass('ui-selecting');
          					selectee.selecting = true;
          					// selectable SELECTING callback
          					self._trigger("selecting", event, {
          						selecting: selectee.element
          					});
          				}
          			} else {
          				// UNSELECT
          				if (selectee.selecting) {
          					if (event.metaKey && selectee.startselected) {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						selectee.$element.addClass('ui-selected');
          						selectee.selected = true;
          					} else {
          						selectee.$element.removeClass('ui-selecting');
          						selectee.selecting = false;
          						if (selectee.startselected) {
          							selectee.$element.addClass('ui-unselecting');
          							selectee.unselecting = true;
          						}
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          				if (selectee.selected) {
          					if (!event.metaKey && !selectee.startselected) {
          						selectee.$element.removeClass('ui-selected');
          						selectee.selected = false;
          
          						selectee.$element.addClass('ui-unselecting');
          						selectee.unselecting = true;
          						// selectable UNSELECTING callback
          						self._trigger("unselecting", event, {
          							unselecting: selectee.element
          						});
          					}
          				}
          			}
          		});
          
          		return false;
          	},
          
          	_mouseStop: function(event) {
          		var self = this;
          
          		this.dragged = false;
          
          		var options = this.options;
          
          		$('.ui-unselecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-unselecting');
          			selectee.unselecting = false;
          			selectee.startselected = false;
          			self._trigger("unselected", event, {
          				unselected: selectee.element
          			});
          		});
          		$('.ui-selecting', this.element[0]).each(function() {
          			var selectee = $.data(this, "selectable-item");
          			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
          			selectee.selecting = false;
          			selectee.selected = true;
          			selectee.startselected = true;
          			self._trigger("selected", event, {
          				selected: selectee.element
          			});
          		});
          		this._trigger("stop", event);
          
          		this.helper.remove();
          
          		return false;
          	}
          
          });
          
          $.extend($.ui.selectable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Sortable 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Sortables
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget("ui.sortable", $.ui.mouse, {
          	widgetEventPrefix: "sort",
          	options: {
          		appendTo: "parent",
          		axis: false,
          		connectWith: false,
          		containment: false,
          		cursor: 'auto',
          		cursorAt: false,
          		dropOnEmpty: true,
          		forcePlaceholderSize: false,
          		forceHelperSize: false,
          		grid: false,
          		handle: false,
          		helper: "original",
          		items: '> *',
          		opacity: false,
          		placeholder: false,
          		revert: false,
          		scroll: true,
          		scrollSensitivity: 20,
          		scrollSpeed: 20,
          		scope: "default",
          		tolerance: "intersect",
          		zIndex: 1000
          	},
          	_create: function() {
          
          		var o = this.options;
          		this.containerCache = {};
          		this.element.addClass("ui-sortable");
          
          		//Get the items
          		this.refresh();
          
          		//Let's determine if the items are floating
          		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
          
          		//Let's determine the parent's offset
          		this.offset = this.element.offset();
          
          		//Initialize mouse events for interaction
          		this._mouseInit();
          
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass("ui-sortable ui-sortable-disabled")
          			.removeData("sortable")
          			.unbind(".sortable");
          		this._mouseDestroy();
          
          		for ( var i = this.items.length - 1; i >= 0; i-- )
          			this.items[i].item.removeData("sortable-item");
          
          		return this;
          	},
          
          	_setOption: function(key, value){
          		if ( key === "disabled" ) {
          			this.options[ key ] = value;
          	
          			this.widget()
          				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
          		} else {
          			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
          			$.Widget.prototype._setOption.apply(this, arguments);
          		}
          	},
          
          	_mouseCapture: function(event, overrideHandle) {
          
          		if (this.reverting) {
          			return false;
          		}
          
          		if(this.options.disabled || this.options.type == 'static') return false;
          
          		//We have to refresh the items data once first
          		this._refreshItems(event);
          
          		//Find out if the clicked node (or one of its parents) is a actual item in this.items
          		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
          			if($.data(this, 'sortable-item') == self) {
          				currentItem = $(this);
          				return false;
          			}
          		});
          		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
          
          		if(!currentItem) return false;
          		if(this.options.handle && !overrideHandle) {
          			var validHandle = false;
          
          			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
          			if(!validHandle) return false;
          		}
          
          		this.currentItem = currentItem;
          		this._removeCurrentsFromItems();
          		return true;
          
          	},
          
          	_mouseStart: function(event, overrideHandle, noActivation) {
          
          		var o = this.options, self = this;
          		this.currentContainer = this;
          
          		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
          		this.refreshPositions();
          
          		//Create and append the visible helper
          		this.helper = this._createHelper(event);
          
          		//Cache the helper size
          		this._cacheHelperProportions();
          
          		/*
          		 * - Position generation -
          		 * This block generates everything position related - it's the core of draggables.
          		 */
          
          		//Cache the margins of the original element
          		this._cacheMargins();
          
          		//Get the next scrolling parent
          		this.scrollParent = this.helper.scrollParent();
          
          		//The element's absolute position on the page minus margins
          		this.offset = this.currentItem.offset();
          		this.offset = {
          			top: this.offset.top - this.margins.top,
          			left: this.offset.left - this.margins.left
          		};
          
          		// Only after we got the offset, we can change the helper's position to absolute
          		// TODO: Still need to figure out a way to make relative sorting possible
          		this.helper.css("position", "absolute");
          		this.cssPosition = this.helper.css("position");
          
          		$.extend(this.offset, {
          			click: { //Where the click happened, relative to the element
          				left: event.pageX - this.offset.left,
          				top: event.pageY - this.offset.top
          			},
          			parent: this._getParentOffset(),
          			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
          		});
          
          		//Generate the original position
          		this.originalPosition = this._generatePosition(event);
          		this.originalPageX = event.pageX;
          		this.originalPageY = event.pageY;
          
          		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
          		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
          
          		//Cache the former DOM position
          		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
          
          		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
          		if(this.helper[0] != this.currentItem[0]) {
          			this.currentItem.hide();
          		}
          
          		//Create the placeholder
          		this._createPlaceholder();
          
          		//Set a containment if given in the options
          		if(o.containment)
          			this._setContainment();
          
          		if(o.cursor) { // cursor option
          			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
          			$('body').css("cursor", o.cursor);
          		}
          
          		if(o.opacity) { // opacity option
          			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
          			this.helper.css("opacity", o.opacity);
          		}
          
          		if(o.zIndex) { // zIndex option
          			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
          			this.helper.css("zIndex", o.zIndex);
          		}
          
          		//Prepare scrolling
          		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
          			this.overflowOffset = this.scrollParent.offset();
          
          		//Call callbacks
          		this._trigger("start", event, this._uiHash());
          
          		//Recache the helper size
          		if(!this._preserveHelperProportions)
          			this._cacheHelperProportions();
          
          
          		//Post 'activate' events to possible containers
          		if(!noActivation) {
          			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
          		}
          
          		//Prepare possible droppables
          		if($.ui.ddmanager)
          			$.ui.ddmanager.current = this;
          
          		if ($.ui.ddmanager && !o.dropBehaviour)
          			$.ui.ddmanager.prepareOffsets(this, event);
          
          		this.dragging = true;
          
          		this.helper.addClass("ui-sortable-helper");
          		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
          		return true;
          
          	},
          
          	_mouseDrag: function(event) {
          
          		//Compute the helpers position
          		this.position = this._generatePosition(event);
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		if (!this.lastPositionAbs) {
          			this.lastPositionAbs = this.positionAbs;
          		}
          
          		//Do scrolling
          		if(this.options.scroll) {
          			var o = this.options, scrolled = false;
          			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
          
          				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
          				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
          					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
          
          				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
          				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
          					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
          
          			} else {
          
          				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
          				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
          					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
          
          				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
          				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
          					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
          
          			}
          
          			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
          				$.ui.ddmanager.prepareOffsets(this, event);
          		}
          
          		//Regenerate the absolute position used for position checks
          		this.positionAbs = this._convertPositionTo("absolute");
          
          		//Set the helper position
          		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
          		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
          
          		//Rearrange
          		for (var i = this.items.length - 1; i >= 0; i--) {
          
          			//Cache variables and intersection, continue if no intersection
          			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
          			if (!intersection) continue;
          
          			if(itemElement != this.currentItem[0] //cannot intersect with itself
          				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
          				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
          				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
          				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
          			) {
          
          				this.direction = intersection == 1 ? "down" : "up";
          
          				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
          					this._rearrange(event, item);
          				} else {
          					break;
          				}
          
          				this._trigger("change", event, this._uiHash());
          				break;
          			}
          		}
          
          		//Post events to containers
          		this._contactContainers(event);
          
          		//Interconnect with droppables
          		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
          
          		//Call callbacks
          		this._trigger('sort', event, this._uiHash());
          
          		this.lastPositionAbs = this.positionAbs;
          		return false;
          
          	},
          
          	_mouseStop: function(event, noPropagation) {
          
          		if(!event) return;
          
          		//If we are using droppables, inform the manager about the drop
          		if ($.ui.ddmanager && !this.options.dropBehaviour)
          			$.ui.ddmanager.drop(this, event);
          
          		if(this.options.revert) {
          			var self = this;
          			var cur = self.placeholder.offset();
          
          			self.reverting = true;
          
          			$(this.helper).animate({
          				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
          				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
          			}, parseInt(this.options.revert, 10) || 500, function() {
          				self._clear(event);
          			});
          		} else {
          			this._clear(event, noPropagation);
          		}
          
          		return false;
          
          	},
          
          	cancel: function() {
          
          		var self = this;
          
          		if(this.dragging) {
          
          			this._mouseUp();
          
          			if(this.options.helper == "original")
          				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          			else
          				this.currentItem.show();
          
          			//Post deactivating events to containers
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", null, self._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
          
          		$.extend(this, {
          			helper: null,
          			dragging: false,
          			reverting: false,
          			_noFinalSort: null
          		});
          
          		if(this.domPosition.prev) {
          			$(this.domPosition.prev).after(this.currentItem);
          		} else {
          			$(this.domPosition.parent).prepend(this.currentItem);
          		}
          
          		return this;
          
          	},
          
          	serialize: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var str = []; o = o || {};
          
          		$(items).each(function() {
          			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
          			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
          		});
          
          		if(!str.length && o.key) {
          			str.push(o.key + '=');
          		}
          
          		return str.join('&');
          
          	},
          
          	toArray: function(o) {
          
          		var items = this._getItemsAsjQuery(o && o.connected);
          		var ret = []; o = o || {};
          
          		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
          		return ret;
          
          	},
          
          	/* Be careful with the following core functions */
          	_intersectsWith: function(item) {
          
          		var x1 = this.positionAbs.left,
          			x2 = x1 + this.helperProportions.width,
          			y1 = this.positionAbs.top,
          			y2 = y1 + this.helperProportions.height;
          
          		var l = item.left,
          			r = l + item.width,
          			t = item.top,
          			b = t + item.height;
          
          		var dyClick = this.offset.click.top,
          			dxClick = this.offset.click.left;
          
          		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
          
          		if(	   this.options.tolerance == "pointer"
          			|| this.options.forcePointerForContainers
          			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
          		) {
          			return isOverElement;
          		} else {
          
          			return (l < x1 + (this.helperProportions.width / 2) // Right Half
          				&& x2 - (this.helperProportions.width / 2) < r // Left Half
          				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
          				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
          
          		}
          	},
          
          	_intersectsWithPointer: function(item) {
          
          		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
          			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
          			isOverElement = isOverElementHeight && isOverElementWidth,
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (!isOverElement)
          			return false;
          
          		return this.floating ?
          			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
          			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
          
          	},
          
          	_intersectsWithSides: function(item) {
          
          		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
          			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
          			verticalDirection = this._getDragVerticalDirection(),
          			horizontalDirection = this._getDragHorizontalDirection();
          
          		if (this.floating && horizontalDirection) {
          			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
          		} else {
          			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
          		}
          
          	},
          
          	_getDragVerticalDirection: function() {
          		var delta = this.positionAbs.top - this.lastPositionAbs.top;
          		return delta != 0 && (delta > 0 ? "down" : "up");
          	},
          
          	_getDragHorizontalDirection: function() {
          		var delta = this.positionAbs.left - this.lastPositionAbs.left;
          		return delta != 0 && (delta > 0 ? "right" : "left");
          	},
          
          	refresh: function(event) {
          		this._refreshItems(event);
          		this.refreshPositions();
          		return this;
          	},
          
          	_connectWith: function() {
          		var options = this.options;
          		return options.connectWith.constructor == String
          			? [options.connectWith]
          			: options.connectWith;
          	},
          	
          	_getItemsAsjQuery: function(connected) {
          
          		var self = this;
          		var items = [];
          		var queries = [];
          		var connectWith = this._connectWith();
          
          		if(connectWith && connected) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
          					}
          				};
          			};
          		}
          
          		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
          
          		for (var i = queries.length - 1; i >= 0; i--){
          			queries[i][0].each(function() {
          				items.push(this);
          			});
          		};
          
          		return $(items);
          
          	},
          
          	_removeCurrentsFromItems: function() {
          
          		var list = this.currentItem.find(":data(sortable-item)");
          
          		for (var i=0; i < this.items.length; i++) {
          
          			for (var j=0; j < list.length; j++) {
          				if(list[j] == this.items[i].item[0])
          					this.items.splice(i,1);
          			};
          
          		};
          
          	},
          
          	_refreshItems: function(event) {
          
          		this.items = [];
          		this.containers = [this];
          		var items = this.items;
          		var self = this;
          		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
          		var connectWith = this._connectWith();
          
          		if(connectWith) {
          			for (var i = connectWith.length - 1; i >= 0; i--){
          				var cur = $(connectWith[i]);
          				for (var j = cur.length - 1; j >= 0; j--){
          					var inst = $.data(cur[j], 'sortable');
          					if(inst && inst != this && !inst.options.disabled) {
          						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
          						this.containers.push(inst);
          					}
          				};
          			};
          		}
          
          		for (var i = queries.length - 1; i >= 0; i--) {
          			var targetData = queries[i][1];
          			var _queries = queries[i][0];
          
          			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
          				var item = $(_queries[j]);
          
          				item.data('sortable-item', targetData); // Data for target checking (mouse manager)
          
          				items.push({
          					item: item,
          					instance: targetData,
          					width: 0, height: 0,
          					left: 0, top: 0
          				});
          			};
          		};
          
          	},
          
          	refreshPositions: function(fast) {
          
          		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
          		if(this.offsetParent && this.helper) {
          			this.offset.parent = this._getParentOffset();
          		}
          
          		for (var i = this.items.length - 1; i >= 0; i--){
          			var item = this.items[i];
          
          			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
          
          			if (!fast) {
          				item.width = t.outerWidth();
          				item.height = t.outerHeight();
          			}
          
          			var p = t.offset();
          			item.left = p.left;
          			item.top = p.top;
          		};
          
          		if(this.options.custom && this.options.custom.refreshContainers) {
          			this.options.custom.refreshContainers.call(this);
          		} else {
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				var p = this.containers[i].element.offset();
          				this.containers[i].containerCache.left = p.left;
          				this.containers[i].containerCache.top = p.top;
          				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
          				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
          			};
          		}
          
          		return this;
          	},
          
          	_createPlaceholder: function(that) {
          
          		var self = that || this, o = self.options;
          
          		if(!o.placeholder || o.placeholder.constructor == String) {
          			var className = o.placeholder;
          			o.placeholder = {
          				element: function() {
          
          					var el = $(document.createElement(self.currentItem[0].nodeName))
          						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
          						.removeClass("ui-sortable-helper")[0];
          
          					if(!className)
          						el.style.visibility = "hidden";
          
          					return el;
          				},
          				update: function(container, p) {
          
          					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
          					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
          					if(className && !o.forcePlaceholderSize) return;
          
          					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
          					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
          					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
          				}
          			};
          		}
          
          		//Create the placeholder
          		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
          
          		//Append it after the actual current item
          		self.currentItem.after(self.placeholder);
          
          		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
          		o.placeholder.update(self, self.placeholder);
          
          	},
          
          	_contactContainers: function(event) {
          		
          		// get innermost container that intersects with item 
          		var innermostContainer = null, innermostIndex = null;		
          		
          		
          		for (var i = this.containers.length - 1; i >= 0; i--){
          
          			// never consider a container that's located within the item itself 
          			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
          				continue;
          
          			if(this._intersectsWith(this.containers[i].containerCache)) {
          
          				// if we've already found a container and it's more "inner" than this, then continue 
          				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
          					continue;
          
          				innermostContainer = this.containers[i]; 
          				innermostIndex = i;
          					
          			} else {
          				// container doesn't intersect. trigger "out" event if necessary 
          				if(this.containers[i].containerCache.over) {
          					this.containers[i]._trigger("out", event, this._uiHash(this));
          					this.containers[i].containerCache.over = 0;
          				}
          			}
          
          		}
          		
          		// if no intersecting containers found, return 
          		if(!innermostContainer) return; 
          
          		// move the item into the container if it's not there already
          		if(this.containers.length === 1) {
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
          			this.containers[innermostIndex].containerCache.over = 1;
          		} else if(this.currentContainer != this.containers[innermostIndex]) { 
          
          			//When entering a new container, we will find the item with the least distance and append our item near it 
          			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
          			for (var j = this.items.length - 1; j >= 0; j--) { 
          				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
          				var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
          				if(Math.abs(cur - base) < dist) { 
          					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
          				} 
          			} 
          
          			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
          				return; 
          
          			this.currentContainer = this.containers[innermostIndex]; 
          			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
          			this._trigger("change", event, this._uiHash()); 
          			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
          
          			//Update the placeholder 
          			this.options.placeholder.update(this.currentContainer, this.placeholder); 
          		
          			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
          			this.containers[innermostIndex].containerCache.over = 1;
          		} 
          	
          		
          	},
          
          	_createHelper: function(event) {
          
          		var o = this.options;
          		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
          
          		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
          			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
          
          		if(helper[0] == this.currentItem[0])
          			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
          
          		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
          		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
          
          		return helper;
          
          	},
          
          	_adjustOffsetFromHelper: function(obj) {
          		if (typeof obj == 'string') {
          			obj = obj.split(' ');
          		}
          		if ($.isArray(obj)) {
          			obj = {left: +obj[0], top: +obj[1] || 0};
          		}
          		if ('left' in obj) {
          			this.offset.click.left = obj.left + this.margins.left;
          		}
          		if ('right' in obj) {
          			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
          		}
          		if ('top' in obj) {
          			this.offset.click.top = obj.top + this.margins.top;
          		}
          		if ('bottom' in obj) {
          			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
          		}
          	},
          
          	_getParentOffset: function() {
          
          
          		//Get the offsetParent and cache its position
          		this.offsetParent = this.helper.offsetParent();
          		var po = this.offsetParent.offset();
          
          		// This is a special case where we need to modify a offset calculated on start, since the following happened:
          		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
          		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
          		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
          		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
          			po.left += this.scrollParent.scrollLeft();
          			po.top += this.scrollParent.scrollTop();
          		}
          
          		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
          		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
          			po = { top: 0, left: 0 };
          
          		return {
          			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
          			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
          		};
          
          	},
          
          	_getRelativeOffset: function() {
          
          		if(this.cssPosition == "relative") {
          			var p = this.currentItem.position();
          			return {
          				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
          				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
          			};
          		} else {
          			return { top: 0, left: 0 };
          		}
          
          	},
          
          	_cacheMargins: function() {
          		this.margins = {
          			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
          			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
          		};
          	},
          
          	_cacheHelperProportions: function() {
          		this.helperProportions = {
          			width: this.helper.outerWidth(),
          			height: this.helper.outerHeight()
          		};
          	},
          
          	_setContainment: function() {
          
          		var o = this.options;
          		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
          		if(o.containment == 'document' || o.containment == 'window') this.containment = [
          			0 - this.offset.relative.left - this.offset.parent.left,
          			0 - this.offset.relative.top - this.offset.parent.top,
          			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
          			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
          		];
          
          		if(!(/^(document|window|parent)$/).test(o.containment)) {
          			var ce = $(o.containment)[0];
          			var co = $(o.containment).offset();
          			var over = ($(ce).css("overflow") != 'hidden');
          
          			this.containment = [
          				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
          				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
          				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
          				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
          			];
          		}
          
          	},
          
          	_convertPositionTo: function(d, pos) {
          
          		if(!pos) pos = this.position;
          		var mod = d == "absolute" ? 1 : -1;
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		return {
          			top: (
          				pos.top																	// The absolute mouse position
          				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
          			),
          			left: (
          				pos.left																// The absolute mouse position
          				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
          				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
          				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
          			)
          		};
          
          	},
          
          	_generatePosition: function(event) {
          
          		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
          
          		// This is another very weird special case that only happens for relative elements:
          		// 1. If the css position is relative
          		// 2. and the scroll parent is the document or similar to the offset parent
          		// we have to refresh the relative offset during the scroll so there are no jumps
          		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
          			this.offset.relative = this._getRelativeOffset();
          		}
          
          		var pageX = event.pageX;
          		var pageY = event.pageY;
          
          		/*
          		 * - Position constraining -
          		 * Constrain the position to a mix of grid, containment.
          		 */
          
          		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
          
          			if(this.containment) {
          				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
          				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
          				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
          			}
          
          			if(o.grid) {
          				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
          				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
          
          				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
          				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
          			}
          
          		}
          
          		return {
          			top: (
          				pageY																// The absolute mouse position
          				- this.offset.click.top													// Click offset (relative to the element)
          				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
          			),
          			left: (
          				pageX																// The absolute mouse position
          				- this.offset.click.left												// Click offset (relative to the element)
          				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
          				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
          				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
          			)
          		};
          
          	},
          
          	_rearrange: function(event, i, a, hardRefresh) {
          
          		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
          
          		//Various things done here to improve the performance:
          		// 1. we create a setTimeout, that calls refreshPositions
          		// 2. on the instance, we have a counter variable, that get's higher after every append
          		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
          		// 4. this lets only the last addition to the timeout stack through
          		this.counter = this.counter ? ++this.counter : 1;
          		var self = this, counter = this.counter;
          
          		window.setTimeout(function() {
          			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
          		},0);
          
          	},
          
          	_clear: function(event, noPropagation) {
          
          		this.reverting = false;
          		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
          		// everything else normalized again
          		var delayedTriggers = [], self = this;
          
          		// We first have to update the dom position of the actual currentItem
          		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
          		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
          		this._noFinalSort = null;
          
          		if(this.helper[0] == this.currentItem[0]) {
          			for(var i in this._storedCSS) {
          				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
          			}
          			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
          		} else {
          			this.currentItem.show();
          		}
          
          		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
          		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
          		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
          			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
          			for (var i = this.containers.length - 1; i >= 0; i--){
          				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
          				}
          			};
          		};
          
          		//Post events to containers
          		for (var i = this.containers.length - 1; i >= 0; i--){
          			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          			if(this.containers[i].containerCache.over) {
          				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
          				this.containers[i].containerCache.over = 0;
          			}
          		}
          
          		//Do what was originally in plugins
          		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
          		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
          		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
          
          		this.dragging = false;
          		if(this.cancelHelperRemoval) {
          			if(!noPropagation) {
          				this._trigger("beforeStop", event, this._uiHash());
          				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          				this._trigger("stop", event, this._uiHash());
          			}
          			return false;
          		}
          
          		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
          
          		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
          		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
          
          		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
          
          		if(!noPropagation) {
          			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
          			this._trigger("stop", event, this._uiHash());
          		}
          
          		this.fromOutside = false;
          		return true;
          
          	},
          
          	_trigger: function() {
          		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
          			this.cancel();
          		}
          	},
          
          	_uiHash: function(inst) {
          		var self = inst || this;
          		return {
          			helper: self.helper,
          			placeholder: self.placeholder || $([]),
          			position: self.position,
          			originalPosition: self.originalPosition,
          			offset: self.positionAbs,
          			item: self.currentItem,
          			sender: inst ? inst.element : null
          		};
          	}
          
          });
          
          $.extend($.ui.sortable, {
          	version: "1.8.6"
          });
          
          })(jQuery);
          /*
           * jQuery UI Effects 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/
           */
          ;jQuery.effects || (function($, undefined) {
          
          $.effects = {};
          
          
          
          /******************************************************************************/
          /****************************** COLOR ANIMATIONS ******************************/
          /******************************************************************************/
          
          // override the animation for color styles
          $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
          	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
          function(i, attr) {
          	$.fx.step[attr] = function(fx) {
          		if (!fx.colorInit) {
          			fx.start = getColor(fx.elem, attr);
          			fx.end = getRGB(fx.end);
          			fx.colorInit = true;
          		}
          
          		fx.elem.style[attr] = 'rgb(' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
          			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
          	};
          });
          
          // Color Conversion functions from highlightFade
          // By Blair Mitchelmore
          // http://jquery.offput.ca/highlightFade/
          
          // Parse strings looking for color tuples [255,255,255]
          function getRGB(color) {
          		var result;
          
          		// Check if we're already dealing with an array of colors
          		if ( color && color.constructor == Array && color.length == 3 )
          				return color;
          
          		// Look for rgb(num,num,num)
          		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
          				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
          
          		// Look for rgb(num%,num%,num%)
          		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
          				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
          
          		// Look for #a0b1c2
          		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
          				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
          
          		// Look for #fff
          		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
          				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
          
          		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
          		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
          				return colors['transparent'];
          
          		// Otherwise, we're most likely dealing with a named color
          		return colors[$.trim(color).toLowerCase()];
          }
          
          function getColor(elem, attr) {
          		var color;
          
          		do {
          				color = $.curCSS(elem, attr);
          
          				// Keep going until we find an element that has color, or we hit the body
          				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
          						break;
          
          				attr = "backgroundColor";
          		} while ( elem = elem.parentNode );
          
          		return getRGB(color);
          };
          
          // Some named colors to work with
          // From Interface by Stefan Petre
          // http://interface.eyecon.ro/
          
          var colors = {
          	aqua:[0,255,255],
          	azure:[240,255,255],
          	beige:[245,245,220],
          	black:[0,0,0],
          	blue:[0,0,255],
          	brown:[165,42,42],
          	cyan:[0,255,255],
          	darkblue:[0,0,139],
          	darkcyan:[0,139,139],
          	darkgrey:[169,169,169],
          	darkgreen:[0,100,0],
          	darkkhaki:[189,183,107],
          	darkmagenta:[139,0,139],
          	darkolivegreen:[85,107,47],
          	darkorange:[255,140,0],
          	darkorchid:[153,50,204],
          	darkred:[139,0,0],
          	darksalmon:[233,150,122],
          	darkviolet:[148,0,211],
          	fuchsia:[255,0,255],
          	gold:[255,215,0],
          	green:[0,128,0],
          	indigo:[75,0,130],
          	khaki:[240,230,140],
          	lightblue:[173,216,230],
          	lightcyan:[224,255,255],
          	lightgreen:[144,238,144],
          	lightgrey:[211,211,211],
          	lightpink:[255,182,193],
          	lightyellow:[255,255,224],
          	lime:[0,255,0],
          	magenta:[255,0,255],
          	maroon:[128,0,0],
          	navy:[0,0,128],
          	olive:[128,128,0],
          	orange:[255,165,0],
          	pink:[255,192,203],
          	purple:[128,0,128],
          	violet:[128,0,128],
          	red:[255,0,0],
          	silver:[192,192,192],
          	white:[255,255,255],
          	yellow:[255,255,0],
          	transparent: [255,255,255]
          };
          
          
          
          /******************************************************************************/
          /****************************** CLASS ANIMATIONS ******************************/
          /******************************************************************************/
          
          var classAnimationActions = ['add', 'remove', 'toggle'],
          	shorthandStyles = {
          		border: 1,
          		borderBottom: 1,
          		borderColor: 1,
          		borderLeft: 1,
          		borderRight: 1,
          		borderTop: 1,
          		borderWidth: 1,
          		margin: 1,
          		padding: 1
          	};
          
          function getElementStyles() {
          	var style = document.defaultView
          			? document.defaultView.getComputedStyle(this, null)
          			: this.currentStyle,
          		newStyle = {},
          		key,
          		camelCase;
          
          	// webkit enumerates style porperties
          	if (style && style.length && style[0] && style[style[0]]) {
          		var len = style.length;
          		while (len--) {
          			key = style[len];
          			if (typeof style[key] == 'string') {
          				camelCase = key.replace(/\-(\w)/g, function(all, letter){
          					return letter.toUpperCase();
          				});
          				newStyle[camelCase] = style[key];
          			}
          		}
          	} else {
          		for (key in style) {
          			if (typeof style[key] === 'string') {
          				newStyle[key] = style[key];
          			}
          		}
          	}
          	
          	return newStyle;
          }
          
          function filterStyles(styles) {
          	var name, value;
          	for (name in styles) {
          		value = styles[name];
          		if (
          			// ignore null and undefined values
          			value == null ||
          			// ignore functions (when does this occur?)
          			$.isFunction(value) ||
          			// shorthand styles that need to be expanded
          			name in shorthandStyles ||
          			// ignore scrollbars (break in IE)
          			(/scrollbar/).test(name) ||
          
          			// only colors or values that can be converted to numbers
          			(!(/color/i).test(name) && isNaN(parseFloat(value)))
          		) {
          			delete styles[name];
          		}
          	}
          	
          	return styles;
          }
          
          function styleDifference(oldStyle, newStyle) {
          	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
          		name;
          
          	for (name in newStyle) {
          		if (oldStyle[name] != newStyle[name]) {
          			diff[name] = newStyle[name];
          		}
          	}
          
          	return diff;
          }
          
          $.effects.animateClass = function(value, duration, easing, callback) {
          	if ($.isFunction(easing)) {
          		callback = easing;
          		easing = null;
          	}
          
          	return this.each(function() {
          
          		var that = $(this),
          			originalStyleAttr = that.attr('style') || ' ',
          			originalStyle = filterStyles(getElementStyles.call(this)),
          			newStyle,
          			className = that.attr('className');
          
          		$.each(classAnimationActions, function(i, action) {
          			if (value[action]) {
          				that[action + 'Class'](value[action]);
          			}
          		});
          		newStyle = filterStyles(getElementStyles.call(this));
          		that.attr('className', className);
          
          		that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
          			$.each(classAnimationActions, function(i, action) {
          				if (value[action]) { that[action + 'Class'](value[action]); }
          			});
          			// work around bug in IE by clearing the cssText before setting it
          			if (typeof that.attr('style') == 'object') {
          				that.attr('style').cssText = '';
          				that.attr('style').cssText = originalStyleAttr;
          			} else {
          				that.attr('style', originalStyleAttr);
          			}
          			if (callback) { callback.apply(this, arguments); }
          		});
          	});
          };
          
          $.fn.extend({
          	_addClass: $.fn.addClass,
          	addClass: function(classNames, speed, easing, callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
          	},
          
          	_removeClass: $.fn.removeClass,
          	removeClass: function(classNames,speed,easing,callback) {
          		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
          	},
          
          	_toggleClass: $.fn.toggleClass,
          	toggleClass: function(classNames, force, speed, easing, callback) {
          		if ( typeof force == "boolean" || force === undefined ) {
          			if ( !speed ) {
          				// without speed parameter;
          				return this._toggleClass(classNames, force);
          			} else {
          				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
          			}
          		} else {
          			// without switch parameter;
          			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
          		}
          	},
          
          	switchClass: function(remove,add,speed,easing,callback) {
          		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EFFECTS **********************************/
          /******************************************************************************/
          
          $.extend($.effects, {
          	version: "1.8.6",
          
          	// Saves a set of properties in a data storage
          	save: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
          		}
          	},
          
          	// Restores a set of previously saved properties from a data storage
          	restore: function(element, set) {
          		for(var i=0; i < set.length; i++) {
          			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
          		}
          	},
          
          	setMode: function(el, mode) {
          		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
          		return mode;
          	},
          
          	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
          		// this should be a little more flexible in the future to handle a string & hash
          		var y, x;
          		switch (origin[0]) {
          			case 'top': y = 0; break;
          			case 'middle': y = 0.5; break;
          			case 'bottom': y = 1; break;
          			default: y = origin[0] / original.height;
          		};
          		switch (origin[1]) {
          			case 'left': x = 0; break;
          			case 'center': x = 0.5; break;
          			case 'right': x = 1; break;
          			default: x = origin[1] / original.width;
          		};
          		return {x: x, y: y};
          	},
          
          	// Wraps the element around a wrapper that copies position properties
          	createWrapper: function(element) {
          
          		// if the element is already wrapped, return it
          		if (element.parent().is('.ui-effects-wrapper')) {
          			return element.parent();
          		}
          
          		// wrap the element
          		var props = {
          				width: element.outerWidth(true),
          				height: element.outerHeight(true),
          				'float': element.css('float')
          			},
          			wrapper = $('<div></div>')
          				.addClass('ui-effects-wrapper')
          				.css({
          					fontSize: '100%',
          					background: 'transparent',
          					border: 'none',
          					margin: 0,
          					padding: 0
          				});
          
          		element.wrap(wrapper);
          		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
          
          		// transfer positioning properties to the wrapper
          		if (element.css('position') == 'static') {
          			wrapper.css({ position: 'relative' });
          			element.css({ position: 'relative' });
          		} else {
          			$.extend(props, {
          				position: element.css('position'),
          				zIndex: element.css('z-index')
          			});
          			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
          				props[pos] = element.css(pos);
          				if (isNaN(parseInt(props[pos], 10))) {
          					props[pos] = 'auto';
          				}
          			});
          			element.css({position: 'relative', top: 0, left: 0 });
          		}
          
          		return wrapper.css(props).show();
          	},
          
          	removeWrapper: function(element) {
          		if (element.parent().is('.ui-effects-wrapper'))
          			return element.parent().replaceWith(element);
          		return element;
          	},
          
          	setTransition: function(element, list, factor, value) {
          		value = value || {};
          		$.each(list, function(i, x){
          			unit = element.cssUnit(x);
          			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
          		});
          		return value;
          	}
          });
          
          
          function _normalizeArguments(effect, options, speed, callback) {
          	// shift params for method overloading
          	if (typeof effect == 'object') {
          		callback = options;
          		speed = null;
          		options = effect;
          		effect = options.effect;
          	}
          	if ($.isFunction(options)) {
          		callback = options;
          		speed = null;
          		options = {};
          	}
                  if (typeof options == 'number' || $.fx.speeds[options]) {
          		callback = speed;
          		speed = options;
          		options = {};
          	}
          	if ($.isFunction(speed)) {
          		callback = speed;
          		speed = null;
          	}
          
          	options = options || {};
          
          	speed = speed || options.duration;
          	speed = $.fx.off ? 0 : typeof speed == 'number'
          		? speed : $.fx.speeds[speed] || $.fx.speeds._default;
          
          	callback = callback || options.complete;
          
          	return [effect, options, speed, callback];
          }
          
          function standardSpeed( speed ) {
          	// valid standard speeds
          	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
          		return true;
          	}
          	
          	// invalid strings - treat as "normal" speed
          	if ( typeof speed === "string" && !$.effects[ speed ] ) {
          		return true;
          	}
          	
          	return false;
          }
          
          $.fn.extend({
          	effect: function(effect, options, speed, callback) {
          		var args = _normalizeArguments.apply(this, arguments),
          			// TODO: make effects take actual parameters instead of a hash
          			args2 = {
          				options: args[1],
          				duration: args[2],
          				callback: args[3]
          			},
          			mode = args2.options.mode,
          			effectMethod = $.effects[effect];
          		
          		if ( $.fx.off || !effectMethod ) {
          			// delegate to the original method (e.g., .show()) if possible
          			if ( mode ) {
          				return this[ mode ]( args2.duration, args2.callback );
          			} else {
          				return this.each(function() {
          					if ( args2.callback ) {
          						args2.callback.call( this );
          					}
          				});
          			}
          		}
          		
          		return effectMethod.call(this, args2);
          	},
          
          	_show: $.fn.show,
          	show: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._show.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'show';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	_hide: $.fn.hide,
          	hide: function(speed) {
          		if ( standardSpeed( speed ) ) {
          			return this._hide.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'hide';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// jQuery core overloads toggle and creates _toggle
          	__toggle: $.fn.toggle,
          	toggle: function(speed) {
          		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
          			return this.__toggle.apply(this, arguments);
          		} else {
          			var args = _normalizeArguments.apply(this, arguments);
          			args[1].mode = 'toggle';
          			return this.effect.apply(this, args);
          		}
          	},
          
          	// helper functions
          	cssUnit: function(key) {
          		var style = this.css(key), val = [];
          		$.each( ['em','px','%','pt'], function(i, unit){
          			if(style.indexOf(unit) > 0)
          				val = [parseFloat(style), unit];
          		});
          		return val;
          	}
          });
          
          
          
          /******************************************************************************/
          /*********************************** EASING ***********************************/
          /******************************************************************************/
          
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           *
           * Open source under the BSD License.
           *
           * Copyright 2008 George McGinley Smith
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          $.easing.jswing = $.easing.swing;
          
          $.extend($.easing,
          {
          	def: 'easeOutQuad',
          	swing: function (x, t, b, c, d) {
          		//alert($.easing.default);
          		return $.easing[$.easing.def](x, t, b, c, d);
          	},
          	easeInQuad: function (x, t, b, c, d) {
          		return c*(t/=d)*t + b;
          	},
          	easeOutQuad: function (x, t, b, c, d) {
          		return -c *(t/=d)*(t-2) + b;
          	},
          	easeInOutQuad: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t + b;
          		return -c/2 * ((--t)*(t-2) - 1) + b;
          	},
          	easeInCubic: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t + b;
          	},
          	easeOutCubic: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t + 1) + b;
          	},
          	easeInOutCubic: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t + b;
          		return c/2*((t-=2)*t*t + 2) + b;
          	},
          	easeInQuart: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t + b;
          	},
          	easeOutQuart: function (x, t, b, c, d) {
          		return -c * ((t=t/d-1)*t*t*t - 1) + b;
          	},
          	easeInOutQuart: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
          		return -c/2 * ((t-=2)*t*t*t - 2) + b;
          	},
          	easeInQuint: function (x, t, b, c, d) {
          		return c*(t/=d)*t*t*t*t + b;
          	},
          	easeOutQuint: function (x, t, b, c, d) {
          		return c*((t=t/d-1)*t*t*t*t + 1) + b;
          	},
          	easeInOutQuint: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
          		return c/2*((t-=2)*t*t*t*t + 2) + b;
          	},
          	easeInSine: function (x, t, b, c, d) {
          		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
          	},
          	easeOutSine: function (x, t, b, c, d) {
          		return c * Math.sin(t/d * (Math.PI/2)) + b;
          	},
          	easeInOutSine: function (x, t, b, c, d) {
          		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
          	},
          	easeInExpo: function (x, t, b, c, d) {
          		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
          	},
          	easeOutExpo: function (x, t, b, c, d) {
          		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          	},
          	easeInOutExpo: function (x, t, b, c, d) {
          		if (t==0) return b;
          		if (t==d) return b+c;
          		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
          		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
          	},
          	easeInCirc: function (x, t, b, c, d) {
          		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
          	},
          	easeOutCirc: function (x, t, b, c, d) {
          		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
          	},
          	easeInOutCirc: function (x, t, b, c, d) {
          		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
          		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
          	},
          	easeInElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          	},
          	easeOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
          	},
          	easeInOutElastic: function (x, t, b, c, d) {
          		var s=1.70158;var p=0;var a=c;
          		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
          		if (a < Math.abs(c)) { a=c; var s=p/4; }
          		else var s = p/(2*Math.PI) * Math.asin (c/a);
          		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
          		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
          	},
          	easeInBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*(t/=d)*t*((s+1)*t - s) + b;
          	},
          	easeOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          	},
          	easeInOutBack: function (x, t, b, c, d, s) {
          		if (s == undefined) s = 1.70158;
          		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
          	},
          	easeInBounce: function (x, t, b, c, d) {
          		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
          	},
          	easeOutBounce: function (x, t, b, c, d) {
          		if ((t/=d) < (1/2.75)) {
          			return c*(7.5625*t*t) + b;
          		} else if (t < (2/2.75)) {
          			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
          		} else if (t < (2.5/2.75)) {
          			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
          		} else {
          			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
          		}
          	},
          	easeInOutBounce: function (x, t, b, c, d) {
          		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
          		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
          	}
          });
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           *
           * Open source under the BSD License.
           *
           * Copyright 2001 Robert Penner
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms, with or without modification,
           * are permitted provided that the following conditions are met:
           *
           * Redistributions of source code must retain the above copyright notice, this list of
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list
           * of conditions and the following disclaimer in the documentation and/or other materials
           * provided with the distribution.
           *
           * Neither the name of the author nor the names of contributors may be used to endorse
           * or promote products derived from this software without specific prior written permission.
           *
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
           * OF THE POSSIBILITY OF SUCH DAMAGE.
           *
           */
          
          })(jQuery);
          /*
           * jQuery UI Effects Blind 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Blind
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.blind = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'vertical') ? 'height' : 'width';
          		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
          		if(mode == 'show') wrapper.css(ref, 0); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = mode == 'show' ? distance : 0;
          
          		// Animate
          		wrapper.animate(animation, o.duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Bounce 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Bounce
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.bounce = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'up'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 5; // Default # of times
          		var speed = o.duration || 250; // Default speed per bounce
          		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          		if (mode == 'hide') distance = distance / (times * 2);
          		if (mode != 'hide') times--;
          
          		// Animate
          		if (mode == 'show') { // Show Bounce
          			var animation = {opacity: 1};
          			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation, speed / 2, o.options.easing);
          			distance = distance / 2;
          			times--;
          		};
          		for (var i = 0; i < times; i++) { // Bounces
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
          			distance = (mode == 'hide') ? distance * 2 : distance / 2;
          		};
          		if (mode == 'hide') { // Last Bounce
          			var animation = {opacity: 0};
          			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          			el.animate(animation, speed / 2, o.options.easing, function(){
          				el.hide(); // Hide
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		} else {
          			var animation1 = {}, animation2 = {};
          			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
          			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
          			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
          				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          				if(o.callback) o.callback.apply(this, arguments); // Callback
          			});
          		};
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Clip 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Clip
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.clip = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','height','width'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'vertical'; // Default direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var animate = el[0].tagName == 'IMG' ? wrapper : el;
          		var ref = {
          			size: (direction == 'vertical') ? 'height' : 'width',
          			position: (direction == 'vertical') ? 'top' : 'left'
          		};
          		var distance = (direction == 'vertical') ? animate.height() : animate.width();
          		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref.size] = mode == 'show' ? distance : 0;
          		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
          
          		// Animate
          		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Drop 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Drop
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.drop = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','opacity'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
          		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {opacity: mode == 'show' ? 1 : 0};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Explode 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Explode
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.explode = function(o) {
          
          	return this.queue(function() {
          
          	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
          
          	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
          	var el = $(this).show().css('visibility', 'hidden');
          	var offset = el.offset();
          
          	//Substract the margins - not fixing the problem yet.
          	offset.top -= parseInt(el.css("marginTop"),10) || 0;
          	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
          
          	var width = el.outerWidth(true);
          	var height = el.outerHeight(true);
          
          	for(var i=0;i<rows;i++) { // =
          		for(var j=0;j<cells;j++) { // ||
          			el
          				.clone()
          				.appendTo('body')
          				.wrap('<div></div>')
          				.css({
          					position: 'absolute',
          					visibility: 'visible',
          					left: -j*(width/cells),
          					top: -i*(height/rows)
          				})
          				.parent()
          				.addClass('ui-effects-explode')
          				.css({
          					position: 'absolute',
          					overflow: 'hidden',
          					width: width/cells,
          					height: height/rows,
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
          					opacity: o.options.mode == 'show' ? 0 : 1
          				}).animate({
          					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
          					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
          					opacity: o.options.mode == 'show' ? 1 : 0
          				}, o.duration || 500);
          		}
          	}
          
          	// Set a timeout, to call the callback approx. when the other animations have finished
          	setTimeout(function() {
          
          		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
          				if(o.callback) o.callback.apply(el[0]); // Callback
          				el.dequeue();
          
          				$('div.ui-effects-explode').remove();
          
          	}, o.duration || 500);
          
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fade 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fade
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fade = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide');
          
          		elem.animate({ opacity: mode }, {
          			queue: false,
          			duration: o.duration,
          			easing: o.options.easing,
          			complete: function() {
          				(o.callback && o.callback.apply(this, arguments));
          				elem.dequeue();
          			}
          		});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Fold 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Fold
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.fold = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
          		var size = o.options.size || 15; // Default fold size
          		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
          		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var widthFirst = ((mode == 'show') != horizFirst);
          		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
          		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
          		var percent = /([0-9]+)%/.exec(size);
          		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
          		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
          
          		// Animation
          		var animation1 = {}, animation2 = {};
          		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
          		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
          
          		// Animate
          		wrapper.animate(animation1, duration, o.options.easing)
          		.animate(animation2, duration, o.options.easing, function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(el[0], arguments); // Callback
          			el.dequeue();
          		});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Highlight 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Highlight
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.highlight = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			props = ['backgroundImage', 'backgroundColor', 'opacity'],
          			mode = $.effects.setMode(elem, o.options.mode || 'show'),
          			animation = {
          				backgroundColor: elem.css('backgroundColor')
          			};
          
          		if (mode == 'hide') {
          			animation.opacity = 0;
          		}
          
          		$.effects.save(elem, props);
          		elem
          			.show()
          			.css({
          				backgroundImage: 'none',
          				backgroundColor: o.options.color || '#ffff99'
          			})
          			.animate(animation, {
          				queue: false,
          				duration: o.duration,
          				easing: o.options.easing,
          				complete: function() {
          					(mode == 'hide' && elem.hide());
          					$.effects.restore(elem, props);
          					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
          					(o.callback && o.callback.apply(this, arguments));
          					elem.dequeue();
          				}
          			});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Pulsate 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Pulsate
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.pulsate = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'show');
          			times = ((o.options.times || 5) * 2) - 1;
          			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
          			isVisible = elem.is(':visible'),
          			animateTo = 0;
          
          		if (!isVisible) {
          			elem.css('opacity', 0).show();
          			animateTo = 1;
          		}
          
          		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
          			times--;
          		}
          
          		for (var i = 0; i < times; i++) {
          			elem.animate({ opacity: animateTo }, duration, o.options.easing);
          			animateTo = (animateTo + 1) % 2;
          		}
          
          		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
          			if (animateTo == 0) {
          				elem.hide();
          			}
          			(o.callback && o.callback.apply(this, arguments));
          		});
          
          		elem
          			.queue('fx', function() { elem.dequeue(); })
          			.dequeue();
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Scale 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Scale
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.puff = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
          			percent = parseInt(o.options.percent, 10) || 150,
          			factor = percent / 100,
          			original = { height: elem.height(), width: elem.width() };
          
          		$.extend(o.options, {
          			fade: true,
          			mode: mode,
          			percent: mode == 'hide' ? percent : 100,
          			from: mode == 'hide'
          				? original
          				: {
          					height: original.height * factor,
          					width: original.width * factor
          				}
          		});
          
          		elem.effect('scale', o.options, o.duration, o.callback);
          		elem.dequeue();
          	});
          };
          
          $.effects.scale = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this);
          
          		// Set options
          		var options = $.extend(true, {}, o.options);
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
          		var direction = o.options.direction || 'both'; // Set default axis
          		var origin = o.options.origin; // The origin of the scaling
          		if (mode != 'effect') { // Set default origin and restore for show/hide
          			options.origin = origin || ['middle','center'];
          			options.restore = true;
          		}
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
          
          		// Adjust
          		var factor = { // Set scaling factor
          			y: direction != 'horizontal' ? (percent / 100) : 1,
          			x: direction != 'vertical' ? (percent / 100) : 1
          		};
          		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
          
          		if (o.options.fade) { // Fade option to support puff
          			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
          			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
          		};
          
          		// Animation
          		options.from = el.from; options.to = el.to; options.mode = mode;
          
          		// Animate
          		el.effect('size', options, o.duration, o.callback);
          		el.dequeue();
          	});
          
          };
          
          $.effects.size = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
          		var props1 = ['position','top','left','overflow','opacity']; // Always restore
          		var props2 = ['width','height','overflow']; // Copy for children
          		var cProps = ['fontSize'];
          		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
          		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var restore = o.options.restore || false; // Default restore
          		var scale = o.options.scale || 'both'; // Default scale mode
          		var origin = o.options.origin; // The origin of the sizing
          		var original = {height: el.height(), width: el.width()}; // Save original
          		el.from = o.options.from || original; // Default from state
          		el.to = o.options.to || original; // Default to state
          		// Adjust
          		if (origin) { // Calculate baseline shifts
          			var baseline = $.effects.getBaseline(origin, original);
          			el.from.top = (original.height - el.from.height) * baseline.y;
          			el.from.left = (original.width - el.from.width) * baseline.x;
          			el.to.top = (original.height - el.to.height) * baseline.y;
          			el.to.left = (original.width - el.to.width) * baseline.x;
          		};
          		var factor = { // Set scaling factor
          			from: {y: el.from.height / original.height, x: el.from.width / original.width},
          			to: {y: el.to.height / original.height, x: el.to.width / original.width}
          		};
          		if (scale == 'box' || scale == 'both') { // Scale the css box
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(vProps);
          				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
          			};
          			if (factor.from.x != factor.to.x) { // Horizontal props scaling
          				props = props.concat(hProps);
          				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
          				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
          			};
          		};
          		if (scale == 'content' || scale == 'both') { // Scale the content
          			if (factor.from.y != factor.to.y) { // Vertical props scaling
          				props = props.concat(cProps);
          				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
          				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
          			};
          		};
          		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		el.css('overflow','hidden').css(el.from); // Shift
          
          		// Animate
          		if (scale == 'content' || scale == 'both') { // Scale the children
          			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
          			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
          			props2 = props.concat(vProps).concat(hProps); // Concat
          			el.find("*[width]").each(function(){
          				child = $(this);
          				if (restore) $.effects.save(child, props2);
          				var c_original = {height: child.height(), width: child.width()}; // Save original
          				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
          				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
          				if (factor.from.y != factor.to.y) { // Vertical props scaling
          					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
          					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
          				};
          				if (factor.from.x != factor.to.x) { // Horizontal props scaling
          					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
          					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
          				};
          				child.css(child.from); // Shift children
          				child.animate(child.to, o.duration, o.options.easing, function(){
          					if (restore) $.effects.restore(child, props2); // Restore children
          				}); // Animate children
          			});
          		};
          
          		// Animate
          		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if (el.to.opacity === 0) {
          				el.css('opacity', el.from.opacity);
          			}
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Shake 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Shake
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.shake = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default direction
          		var distance = o.options.distance || 20; // Default distance
          		var times = o.options.times || 3; // Default # of times
          		var speed = o.duration || o.options.duration || 140; // Default speed per shake
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          
          		// Animation
          		var animation = {}, animation1 = {}, animation2 = {};
          		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
          		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
          		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
          
          		// Animate
          		el.animate(animation, speed, o.options.easing);
          		for (var i = 1; i < times; i++) { // Shakes
          			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
          		};
          		el.animate(animation1, speed, o.options.easing).
          		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          		});
          		el.queue('fx', function() { el.dequeue(); });
          		el.dequeue();
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Slide 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Slide
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.slide = function(o) {
          
          	return this.queue(function() {
          
          		// Create element
          		var el = $(this), props = ['position','top','left'];
          
          		// Set options
          		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
          		var direction = o.options.direction || 'left'; // Default Direction
          
          		// Adjust
          		$.effects.save(el, props); el.show(); // Save & Show
          		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
          		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
          		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
          		var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
          		if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
          
          		// Animation
          		var animation = {};
          		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
          
          		// Animate
          		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
          			if(mode == 'hide') el.hide(); // Hide
          			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
          			if(o.callback) o.callback.apply(this, arguments); // Callback
          			el.dequeue();
          		}});
          
          	});
          
          };
          
          })(jQuery);
          /*
           * jQuery UI Effects Transfer 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Effects/Transfer
           *
           * Depends:
           *	jquery.effects.core.js
           */
          (function( $, undefined ) {
          
          $.effects.transfer = function(o) {
          	return this.queue(function() {
          		var elem = $(this),
          			target = $(o.options.to),
          			endPosition = target.offset(),
          			animation = {
          				top: endPosition.top,
          				left: endPosition.left,
          				height: target.innerHeight(),
          				width: target.innerWidth()
          			},
          			startPosition = elem.offset(),
          			transfer = $('<div class="ui-effects-transfer"></div>')
          				.appendTo(document.body)
          				.addClass(o.options.className)
          				.css({
          					top: startPosition.top,
          					left: startPosition.left,
          					height: elem.innerHeight(),
          					width: elem.innerWidth(),
          					position: 'absolute'
          				})
          				.animate(animation, o.duration, o.options.easing, function() {
          					transfer.remove();
          					(o.callback && o.callback.apply(elem[0], arguments));
          					elem.dequeue();
          				});
          	});
          };
          
          })(jQuery);
          /*
           * jQuery UI Accordion 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Accordion
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.accordion", {
          	options: {
          		active: 0,
          		animated: "slide",
          		autoHeight: true,
          		clearStyle: false,
          		collapsible: false,
          		event: "click",
          		fillSpace: false,
          		header: "> li > :first-child,> :not(li):even",
          		icons: {
          			header: "ui-icon-triangle-1-e",
          			headerSelected: "ui-icon-triangle-1-s"
          		},
          		navigation: false,
          		navigationFilter: function() {
          			return this.href.toLowerCase() === location.href.toLowerCase();
          		}
          	},
          
          	_create: function() {
          		var self = this,
          			options = self.options;
          
          		self.running = 0;
          
          		self.element
          			.addClass( "ui-accordion ui-widget ui-helper-reset" )
          			// in lack of child-selectors in CSS
          			// we need to mark top-LIs in a UL-accordion for some IE-fix
          			.children( "li" )
          				.addClass( "ui-accordion-li-fix" );
          
          		self.headers = self.element.find( options.header )
          			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
          			.bind( "mouseenter.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          			})
          			.bind( "mouseleave.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.bind( "focus.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-focus" );
          			})
          			.bind( "blur.accordion", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		self.headers.next()
          			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
          
          		if ( options.navigation ) {
          			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
          			if ( current.length ) {
          				var header = current.closest( ".ui-accordion-header" );
          				if ( header.length ) {
          					// anchor within header
          					self.active = header;
          				} else {
          					// anchor within content
          					self.active = current.closest( ".ui-accordion-content" ).prev();
          				}
          			}
          		}
          
          		self.active = self._findActive( self.active || options.active )
          			.addClass( "ui-state-default ui-state-active" )
          			.toggleClass( "ui-corner-all" )
          			.toggleClass( "ui-corner-top" );
          		self.active.next().addClass( "ui-accordion-content-active" );
          
          		self._createIcons();
          		self.resize();
          		
          		// ARIA
          		self.element.attr( "role", "tablist" );
          
          		self.headers
          			.attr( "role", "tab" )
          			.bind( "keydown.accordion", function( event ) {
          				return self._keydown( event );
          			})
          			.next()
          				.attr( "role", "tabpanel" );
          
          		self.headers
          			.not( self.active || "" )
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.next()
          				.hide();
          
          		// make sure at least one header is in the tab order
          		if ( !self.active.length ) {
          			self.headers.eq( 0 ).attr( "tabIndex", 0 );
          		} else {
          			self.active
          				.attr({
          					"aria-expanded": "true",
          					tabIndex: 0
          				});
          		}
          
          		// only need links in tab order for Safari
          		if ( !$.browser.safari ) {
          			self.headers.find( "a" ).attr( "tabIndex", -1 );
          		}
          
          		if ( options.event ) {
          			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
          				self._clickHandler.call( self, event, this );
          				event.preventDefault();
          			});
          		}
          	},
          
          	_createIcons: function() {
          		var options = this.options;
          		if ( options.icons ) {
          			$( "<span></span>" )
          				.addClass( "ui-icon " + options.icons.header )
          				.prependTo( this.headers );
          			this.active.children( ".ui-icon" )
          				.toggleClass(options.icons.header)
          				.toggleClass(options.icons.headerSelected);
          			this.element.addClass( "ui-accordion-icons" );
          		}
          	},
          
          	_destroyIcons: function() {
          		this.headers.children( ".ui-icon" ).remove();
          		this.element.removeClass( "ui-accordion-icons" );
          	},
          
          	destroy: function() {
          		var options = this.options;
          
          		this.element
          			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
          			.removeAttr( "role" );
          
          		this.headers
          			.unbind( ".accordion" )
          			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-expanded" )
          			.removeAttr( "tabIndex" );
          
          		this.headers.find( "a" ).removeAttr( "tabIndex" );
          		this._destroyIcons();
          		var contents = this.headers.next()
          			.css( "display", "" )
          			.removeAttr( "role" )
          			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
          		if ( options.autoHeight || options.fillHeight ) {
          			contents.css( "height", "" );
          		}
          
          		return $.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          			
          		if ( key == "active" ) {
          			this.activate( value );
          		}
          		if ( key == "icons" ) {
          			this._destroyIcons();
          			if ( value ) {
          				this._createIcons();
          			}
          		}
          		// #5332 - opacity doesn't cascade to positioned elements in IE
          		// so we need to add the disabled class to the headers and panels
          		if ( key == "disabled" ) {
          			this.headers.add(this.headers.next())
          				[ value ? "addClass" : "removeClass" ](
          					"ui-accordion-disabled ui-state-disabled" );
          		}
          	},
          
          	_keydown: function( event ) {
          		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
          			return;
          		}
          
          		var keyCode = $.ui.keyCode,
          			length = this.headers.length,
          			currentIndex = this.headers.index( event.target ),
          			toFocus = false;
          
          		switch ( event.keyCode ) {
          			case keyCode.RIGHT:
          			case keyCode.DOWN:
          				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
          				break;
          			case keyCode.LEFT:
          			case keyCode.UP:
          				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
          				break;
          			case keyCode.SPACE:
          			case keyCode.ENTER:
          				this._clickHandler( { target: event.target }, event.target );
          				event.preventDefault();
          		}
          
          		if ( toFocus ) {
          			$( event.target ).attr( "tabIndex", -1 );
          			$( toFocus ).attr( "tabIndex", 0 );
          			toFocus.focus();
          			return false;
          		}
          
          		return true;
          	},
          
          	resize: function() {
          		var options = this.options,
          			maxHeight;
          
          		if ( options.fillSpace ) {
          			if ( $.browser.msie ) {
          				var defOverflow = this.element.parent().css( "overflow" );
          				this.element.parent().css( "overflow", "hidden");
          			}
          			maxHeight = this.element.parent().height();
          			if ($.browser.msie) {
          				this.element.parent().css( "overflow", defOverflow );
          			}
          
          			this.headers.each(function() {
          				maxHeight -= $( this ).outerHeight( true );
          			});
          
          			this.headers.next()
          				.each(function() {
          					$( this ).height( Math.max( 0, maxHeight -
          						$( this ).innerHeight() + $( this ).height() ) );
          				})
          				.css( "overflow", "auto" );
          		} else if ( options.autoHeight ) {
          			maxHeight = 0;
          			this.headers.next()
          				.each(function() {
          					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
          				})
          				.height( maxHeight );
          		}
          
          		return this;
          	},
          
          	activate: function( index ) {
          		// TODO this gets called on init, changing the option without an explicit call for that
          		this.options.active = index;
          		// call clickHandler with custom event
          		var active = this._findActive( index )[ 0 ];
          		this._clickHandler( { target: active }, active );
          
          		return this;
          	},
          
          	_findActive: function( selector ) {
          		return selector
          			? typeof selector === "number"
          				? this.headers.filter( ":eq(" + selector + ")" )
          				: this.headers.not( this.headers.not( selector ) )
          			: selector === false
          				? $( [] )
          				: this.headers.filter( ":eq(0)" );
          	},
          
          	// TODO isn't event.target enough? why the separate target argument?
          	_clickHandler: function( event, target ) {
          		var options = this.options;
          		if ( options.disabled ) {
          			return;
          		}
          
          		// called only when using activate(false) to close all parts programmatically
          		if ( !event.target ) {
          			if ( !options.collapsible ) {
          				return;
          			}
          			this.active
          				.removeClass( "ui-state-active ui-corner-top" )
          				.addClass( "ui-state-default ui-corner-all" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.headerSelected )
          					.addClass( options.icons.header );
          			this.active.next().addClass( "ui-accordion-content-active" );
          			var toHide = this.active.next(),
          				data = {
          					options: options,
          					newHeader: $( [] ),
          					oldHeader: options.active,
          					newContent: $( [] ),
          					oldContent: toHide
          				},
          				toShow = ( this.active = $( [] ) );
          			this._toggle( toShow, toHide, data );
          			return;
          		}
          
          		// get the click target
          		var clicked = $( event.currentTarget || target ),
          			clickedIsActive = clicked[0] === this.active[0];
          
          		// TODO the option is changed, is that correct?
          		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
          		options.active = options.collapsible && clickedIsActive ?
          			false :
          			this.headers.index( clicked );
          
          		// if animations are still active, or the active header is the target, ignore click
          		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
          			return;
          		}
          
          		// switch classes
          		this.active
          			.removeClass( "ui-state-active ui-corner-top" )
          			.addClass( "ui-state-default ui-corner-all" )
          			.children( ".ui-icon" )
          				.removeClass( options.icons.headerSelected )
          				.addClass( options.icons.header );
          		if ( !clickedIsActive ) {
          			clicked
          				.removeClass( "ui-state-default ui-corner-all" )
          				.addClass( "ui-state-active ui-corner-top" )
          				.children( ".ui-icon" )
          					.removeClass( options.icons.header )
          					.addClass( options.icons.headerSelected );
          			clicked
          				.next()
          				.addClass( "ui-accordion-content-active" );
          		}
          
          		// find elements to show and hide
          		var toShow = clicked.next(),
          			toHide = this.active.next(),
          			data = {
          				options: options,
          				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
          				oldHeader: this.active,
          				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
          				oldContent: toHide
          			},
          			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
          
          		this.active = clickedIsActive ? $([]) : clicked;
          		this._toggle( toShow, toHide, data, clickedIsActive, down );
          
          		return;
          	},
          
          	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
          		var self = this,
          			options = self.options;
          
          		self.toShow = toShow;
          		self.toHide = toHide;
          		self.data = data;
          
          		var complete = function() {
          			if ( !self ) {
          				return;
          			}
          			return self._completed.apply( self, arguments );
          		};
          
          		// trigger changestart event
          		self._trigger( "changestart", null, self.data );
          
          		// count elements to animate
          		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
          
          		if ( options.animated ) {
          			var animOptions = {};
          
          			if ( options.collapsible && clickedIsActive ) {
          				animOptions = {
          					toShow: $( [] ),
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			} else {
          				animOptions = {
          					toShow: toShow,
          					toHide: toHide,
          					complete: complete,
          					down: down,
          					autoHeight: options.autoHeight || options.fillSpace
          				};
          			}
          
          			if ( !options.proxied ) {
          				options.proxied = options.animated;
          			}
          
          			if ( !options.proxiedDuration ) {
          				options.proxiedDuration = options.duration;
          			}
          
          			options.animated = $.isFunction( options.proxied ) ?
          				options.proxied( animOptions ) :
          				options.proxied;
          
          			options.duration = $.isFunction( options.proxiedDuration ) ?
          				options.proxiedDuration( animOptions ) :
          				options.proxiedDuration;
          
          			var animations = $.ui.accordion.animations,
          				duration = options.duration,
          				easing = options.animated;
          
          			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
          				easing = "slide";
          			}
          			if ( !animations[ easing ] ) {
          				animations[ easing ] = function( options ) {
          					this.slide( options, {
          						easing: easing,
          						duration: duration || 700
          					});
          				};
          			}
          
          			animations[ easing ]( animOptions );
          		} else {
          			if ( options.collapsible && clickedIsActive ) {
          				toShow.toggle();
          			} else {
          				toHide.hide();
          				toShow.show();
          			}
          
          			complete( true );
          		}
          
          		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
          		toHide.prev()
          			.attr({
          				"aria-expanded": "false",
          				tabIndex: -1
          			})
          			.blur();
          		toShow.prev()
          			.attr({
          				"aria-expanded": "true",
          				tabIndex: 0
          			})
          			.focus();
          	},
          
          	_completed: function( cancel ) {
          		this.running = cancel ? 0 : --this.running;
          		if ( this.running ) {
          			return;
          		}
          
          		if ( this.options.clearStyle ) {
          			this.toShow.add( this.toHide ).css({
          				height: "",
          				overflow: ""
          			});
          		}
          
          		// other classes are removed before the animation; this one needs to stay until completed
          		this.toHide.removeClass( "ui-accordion-content-active" );
          
          		this._trigger( "change", null, this.data );
          	}
          });
          
          $.extend( $.ui.accordion, {
          	version: "1.8.6",
          	animations: {
          		slide: function( options, additions ) {
          			options = $.extend({
          				easing: "swing",
          				duration: 300
          			}, options, additions );
          			if ( !options.toHide.size() ) {
          				options.toShow.animate({
          					height: "show",
          					paddingTop: "show",
          					paddingBottom: "show"
          				}, options );
          				return;
          			}
          			if ( !options.toShow.size() ) {
          				options.toHide.animate({
          					height: "hide",
          					paddingTop: "hide",
          					paddingBottom: "hide"
          				}, options );
          				return;
          			}
          			var overflow = options.toShow.css( "overflow" ),
          				percentDone = 0,
          				showProps = {},
          				hideProps = {},
          				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
          				originalWidth;
          			// fix width before calculating height of hidden element
          			var s = options.toShow;
          			originalWidth = s[0].style.width;
          			s.width( parseInt( s.parent().width(), 10 )
          				- parseInt( s.css( "paddingLeft" ), 10 )
          				- parseInt( s.css( "paddingRight" ), 10 )
          				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
          				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
          
          			$.each( fxAttrs, function( i, prop ) {
          				hideProps[ prop ] = "hide";
          
          				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
          				showProps[ prop ] = {
          					value: parts[ 1 ],
          					unit: parts[ 2 ] || "px"
          				};
          			});
          			options.toShow.css({ height: 0, overflow: "hidden" }).show();
          			options.toHide
          				.filter( ":hidden" )
          					.each( options.complete )
          				.end()
          				.filter( ":visible" )
          				.animate( hideProps, {
          				step: function( now, settings ) {
          					// only calculate the percent when animating height
          					// IE gets very inconsistent results when animating elements
          					// with small values, which is common for padding
          					if ( settings.prop == "height" ) {
          						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
          							( settings.now - settings.start ) / ( settings.end - settings.start );
          					}
          
          					options.toShow[ 0 ].style[ settings.prop ] =
          						( percentDone * showProps[ settings.prop ].value )
          						+ showProps[ settings.prop ].unit;
          				},
          				duration: options.duration,
          				easing: options.easing,
          				complete: function() {
          					if ( !options.autoHeight ) {
          						options.toShow.css( "height", "" );
          					}
          					options.toShow.css({
          						width: originalWidth,
          						overflow: overflow
          					});
          					options.complete();
          				}
          			});
          		},
          		bounceslide: function( options ) {
          			this.slide( options, {
          				easing: options.down ? "easeOutBounce" : "swing",
          				duration: options.down ? 1000 : 200
          			});
          		}
          	}
          });
          
          })( jQuery );
          /*
           * jQuery UI Autocomplete 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Autocomplete
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *	jquery.ui.position.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.autocomplete", {
          	options: {
          		appendTo: "body",
          		delay: 300,
          		minLength: 1,
          		position: {
          			my: "left top",
          			at: "left bottom",
          			collision: "none"
          		},
          		source: null
          	},
          	_create: function() {
          		var self = this,
          			doc = this.element[ 0 ].ownerDocument,
          			suppressKeyPress;
          
          		this.element
          			.addClass( "ui-autocomplete-input" )
          			.attr( "autocomplete", "off" )
          			// TODO verify these actually work as intended
          			.attr({
          				role: "textbox",
          				"aria-autocomplete": "list",
          				"aria-haspopup": "true"
          			})
          			.bind( "keydown.autocomplete", function( event ) {
          				if ( self.options.disabled || self.element.attr( "readonly" ) ) {
          					return;
          				}
          
          				suppressKeyPress = false;
          				var keyCode = $.ui.keyCode;
          				switch( event.keyCode ) {
          				case keyCode.PAGE_UP:
          					self._move( "previousPage", event );
          					break;
          				case keyCode.PAGE_DOWN:
          					self._move( "nextPage", event );
          					break;
          				case keyCode.UP:
          					self._move( "previous", event );
          					// prevent moving cursor to beginning of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.DOWN:
          					self._move( "next", event );
          					// prevent moving cursor to end of text field in some browsers
          					event.preventDefault();
          					break;
          				case keyCode.ENTER:
          				case keyCode.NUMPAD_ENTER:
          					// when menu is open and has focus
          					if ( self.menu.active ) {
          						// #6055 - Opera still allows the keypress to occur
          						// which causes forms to submit
          						suppressKeyPress = true;
          						event.preventDefault();
          					}
          					//passthrough - ENTER and TAB both select the current element
          				case keyCode.TAB:
          					if ( !self.menu.active ) {
          						return;
          					}
          					self.menu.select( event );
          					break;
          				case keyCode.ESCAPE:
          					self.element.val( self.term );
          					self.close( event );
          					break;
          				default:
          					// keypress is triggered before the input value is changed
          					clearTimeout( self.searching );
          					self.searching = setTimeout(function() {
          						// only search if the value has changed
          						if ( self.term != self.element.val() ) {
          							self.selectedItem = null;
          							self.search( null, event );
          						}
          					}, self.options.delay );
          					break;
          				}
          			})
          			.bind( "keypress.autocomplete", function( event ) {
          				if ( suppressKeyPress ) {
          					suppressKeyPress = false;
          					event.preventDefault();
          				}
          			})
          			.bind( "focus.autocomplete", function() {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				self.selectedItem = null;
          				self.previous = self.element.val();
          			})
          			.bind( "blur.autocomplete", function( event ) {
          				if ( self.options.disabled ) {
          					return;
          				}
          
          				clearTimeout( self.searching );
          				// clicks on the menu (or a button to trigger a search) will cause a blur event
          				self.closing = setTimeout(function() {
          					self.close( event );
          					self._change( event );
          				}, 150 );
          			});
          		this._initSource();
          		this.response = function() {
          			return self._response.apply( self, arguments );
          		};
          		this.menu = $( "<ul></ul>" )
          			.addClass( "ui-autocomplete" )
          			.appendTo( $( this.options.appendTo || "body", doc )[0] )
          			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
          			.mousedown(function( event ) {
          				// clicking on the scrollbar causes focus to shift to the body
          				// but we can't detect a mouseup or a click immediately afterward
          				// so we have to track the next mousedown and close the menu if
          				// the user clicks somewhere outside of the autocomplete
          				var menuElement = self.menu.element[ 0 ];
          				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
          					setTimeout(function() {
          						$( document ).one( 'mousedown', function( event ) {
          							if ( event.target !== self.element[ 0 ] &&
          								event.target !== menuElement &&
          								!$.ui.contains( menuElement, event.target ) ) {
          								self.close();
          							}
          						});
          					}, 1 );
          				}
          
          				// use another timeout to make sure the blur-event-handler on the input was already triggered
          				setTimeout(function() {
          					clearTimeout( self.closing );
          				}, 13);
          			})
          			.menu({
          				focus: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" );
          					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          						// use value to match what will end up in the input, if it was a key event
          						if ( /^key/.test(event.originalEvent.type) ) {
          							self.element.val( item.value );
          						}
          					}
          				},
          				selected: function( event, ui ) {
          					var item = ui.item.data( "item.autocomplete" ),
          						previous = self.previous;
          
          					// only trigger when focus was lost (click on menu)
          					if ( self.element[0] !== doc.activeElement ) {
          						self.element.focus();
          						self.previous = previous;
          						// #6109 - IE triggers two focus events and the second
          						// is asynchronous, so we need to reset the previous
          						// term synchronously and asynchronously :-(
          						setTimeout(function() {
          							self.previous = previous;
          						}, 1);
          					}
          
          					if ( false !== self._trigger( "select", event, { item: item } ) ) {
          						self.element.val( item.value );
          					}
          					// reset the term after the select event
          					// this allows custom select handling to work properly
          					self.term = self.element.val();
          
          					self.close( event );
          					self.selectedItem = item;
          				},
          				blur: function( event, ui ) {
          					// don't set the value of the text field if it's already correct
          					// this prevents moving the cursor unnecessarily
          					if ( self.menu.element.is(":visible") &&
          						( self.element.val() !== self.term ) ) {
          						self.element.val( self.term );
          					}
          				}
          			})
          			.zIndex( this.element.zIndex() + 1 )
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.hide()
          			.data( "menu" );
          		if ( $.fn.bgiframe ) {
          			 this.menu.element.bgiframe();
          		}
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-autocomplete-input" )
          			.removeAttr( "autocomplete" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-autocomplete" )
          			.removeAttr( "aria-haspopup" );
          		this.menu.element.remove();
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "source" ) {
          			this._initSource();
          		}
          		if ( key === "appendTo" ) {
          			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
          		}
          	},
          
          	_initSource: function() {
          		var self = this,
          			array,
          			url;
          		if ( $.isArray(this.options.source) ) {
          			array = this.options.source;
          			this.source = function( request, response ) {
          				response( $.ui.autocomplete.filter(array, request.term) );
          			};
          		} else if ( typeof this.options.source === "string" ) {
          			url = this.options.source;
          			this.source = function( request, response ) {
          				if (self.xhr) {
          					self.xhr.abort();
          				}
          				self.xhr = $.getJSON( url, request, function( data, status, xhr ) {
          					if ( xhr === self.xhr ) {
          						response( data );
          					}
          					self.xhr = null;
          				});
          			};
          		} else {
          			this.source = this.options.source;
          		}
          	},
          
          	search: function( value, event ) {
          		value = value != null ? value : this.element.val();
          
          		// always save the actual value, not the one passed as an argument
          		this.term = this.element.val();
          
          		if ( value.length < this.options.minLength ) {
          			return this.close( event );
          		}
          
          		clearTimeout( this.closing );
          		if ( this._trigger( "search", event ) === false ) {
          			return;
          		}
          
          		return this._search( value );
          	},
          
          	_search: function( value ) {
          		this.element.addClass( "ui-autocomplete-loading" );
          
          		this.source( { term: value }, this.response );
          	},
          
          	_response: function( content ) {
          		if ( content && content.length ) {
          			content = this._normalize( content );
          			this._suggest( content );
          			this._trigger( "open" );
          		} else {
          			this.close();
          		}
          		this.element.removeClass( "ui-autocomplete-loading" );
          	},
          
          	close: function( event ) {
          		clearTimeout( this.closing );
          		if ( this.menu.element.is(":visible") ) {
          			this._trigger( "close", event );
          			this.menu.element.hide();
          			this.menu.deactivate();
          		}
          	},
          	
          	_change: function( event ) {
          		if ( this.previous !== this.element.val() ) {
          			this._trigger( "change", event, { item: this.selectedItem } );
          		}
          	},
          
          	_normalize: function( items ) {
          		// assume all items have the right format when the first item is complete
          		if ( items.length && items[0].label && items[0].value ) {
          			return items;
          		}
          		return $.map( items, function(item) {
          			if ( typeof item === "string" ) {
          				return {
          					label: item,
          					value: item
          				};
          			}
          			return $.extend({
          				label: item.label || item.value,
          				value: item.value || item.label
          			}, item );
          		});
          	},
          
          	_suggest: function( items ) {
          		var ul = this.menu.element
          			.empty()
          			.zIndex( this.element.zIndex() + 1 );
          		this._renderMenu( ul, items );
          		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
          		this.menu.deactivate();
          		this.menu.refresh();
          		this.menu.element.show().position( $.extend({
          			of: this.element
          		}, this.options.position ));
          
          		this._resizeMenu();
          	},
          
          	_resizeMenu: function() {
          		var ul = this.menu.element;
          		ul.outerWidth( Math.max(
          			ul.width( "" ).outerWidth(),
          			this.element.outerWidth()
          		) );
          	},
          
          	_renderMenu: function( ul, items ) {
          		var self = this;
          		$.each( items, function( index, item ) {
          			self._renderItem( ul, item );
          		});
          	},
          
          	_renderItem: function( ul, item) {
          		return $( "<li></li>" )
          			.data( "item.autocomplete", item )
          			.append( $( "<a></a>" ).text( item.label ) )
          			.appendTo( ul );
          	},
          
          	_move: function( direction, event ) {
          		if ( !this.menu.element.is(":visible") ) {
          			this.search( null, event );
          			return;
          		}
          		if ( this.menu.first() && /^previous/.test(direction) ||
          				this.menu.last() && /^next/.test(direction) ) {
          			this.element.val( this.term );
          			this.menu.deactivate();
          			return;
          		}
          		this.menu[ direction ]( event );
          	},
          
          	widget: function() {
          		return this.menu.element;
          	}
          });
          
          $.extend( $.ui.autocomplete, {
          	escapeRegex: function( value ) {
          		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
          	},
          	filter: function(array, term) {
          		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
          		return $.grep( array, function(value) {
          			return matcher.test( value.label || value.value || value );
          		});
          	}
          });
          
          }( jQuery ));
          
          /*
           * jQuery UI Menu (not officially released)
           * 
           * This widget isn't yet finished and the API is subject to change. We plan to finish
           * it for the next release. You're welcome to give it a try anyway and give us feedback,
           * as long as you're okay with migrating your code later on. We can help with that, too.
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Menu
           *
           * Depends:
           *	jquery.ui.core.js
           *  jquery.ui.widget.js
           */
          (function($) {
          
          $.widget("ui.menu", {
          	_create: function() {
          		var self = this;
          		this.element
          			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
          			.attr({
          				role: "listbox",
          				"aria-activedescendant": "ui-active-menuitem"
          			})
          			.click(function( event ) {
          				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
          					return;
          				}
          				// temporary
          				event.preventDefault();
          				self.select( event );
          			});
          		this.refresh();
          	},
          	
          	refresh: function() {
          		var self = this;
          
          		// don't refresh list items that are already adapted
          		var items = this.element.children("li:not(.ui-menu-item):has(a)")
          			.addClass("ui-menu-item")
          			.attr("role", "menuitem");
          		
          		items.children("a")
          			.addClass("ui-corner-all")
          			.attr("tabindex", -1)
          			// mouseenter doesn't work with event delegation
          			.mouseenter(function( event ) {
          				self.activate( event, $(this).parent() );
          			})
          			.mouseleave(function() {
          				self.deactivate();
          			});
          	},
          
          	activate: function( event, item ) {
          		this.deactivate();
          		if (this.hasScroll()) {
          			var offset = item.offset().top - this.element.offset().top,
          				scroll = this.element.attr("scrollTop"),
          				elementHeight = this.element.height();
          			if (offset < 0) {
          				this.element.attr("scrollTop", scroll + offset);
          			} else if (offset >= elementHeight) {
          				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
          			}
          		}
          		this.active = item.eq(0)
          			.children("a")
          				.addClass("ui-state-hover")
          				.attr("id", "ui-active-menuitem")
          			.end();
          		this._trigger("focus", event, { item: item });
          	},
          
          	deactivate: function() {
          		if (!this.active) { return; }
          
          		this.active.children("a")
          			.removeClass("ui-state-hover")
          			.removeAttr("id");
          		this._trigger("blur");
          		this.active = null;
          	},
          
          	next: function(event) {
          		this.move("next", ".ui-menu-item:first", event);
          	},
          
          	previous: function(event) {
          		this.move("prev", ".ui-menu-item:last", event);
          	},
          
          	first: function() {
          		return this.active && !this.active.prevAll(".ui-menu-item").length;
          	},
          
          	last: function() {
          		return this.active && !this.active.nextAll(".ui-menu-item").length;
          	},
          
          	move: function(direction, edge, event) {
          		if (!this.active) {
          			this.activate(event, this.element.children(edge));
          			return;
          		}
          		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
          		if (next.length) {
          			this.activate(event, next);
          		} else {
          			this.activate(event, this.element.children(edge));
          		}
          	},
          
          	// TODO merge with previousPage
          	nextPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.last()) {
          				this.activate(event, this.element.children(".ui-menu-item:first"));
          				return;
          			}
          			var base = this.active.offset().top,
          				height = this.element.height(),
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base - height + $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:last");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.last() ? ":first" : ":last"));
          		}
          	},
          
          	// TODO merge with nextPage
          	previousPage: function(event) {
          		if (this.hasScroll()) {
          			// TODO merge with no-scroll-else
          			if (!this.active || this.first()) {
          				this.activate(event, this.element.children(".ui-menu-item:last"));
          				return;
          			}
          
          			var base = this.active.offset().top,
          				height = this.element.height();
          				result = this.element.children(".ui-menu-item").filter(function() {
          					var close = $(this).offset().top - base + height - $(this).height();
          					// TODO improve approximation
          					return close < 10 && close > -10;
          				});
          
          			// TODO try to catch this earlier when scrollTop indicates the last page anyway
          			if (!result.length) {
          				result = this.element.children(".ui-menu-item:first");
          			}
          			this.activate(event, result);
          		} else {
          			this.activate(event, this.element.children(".ui-menu-item")
          				.filter(!this.active || this.first() ? ":last" : ":first"));
          		}
          	},
          
          	hasScroll: function() {
          		return this.element.height() < this.element.attr("scrollHeight");
          	},
          
          	select: function( event ) {
          		this._trigger("selected", event, { item: this.active });
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Button 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Button
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var lastActive,
          	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
          	stateClasses = "ui-state-hover ui-state-active ",
          	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
          	formResetHandler = function( event ) {
          		$( ":ui-button", event.target.form ).each(function() {
          			var inst = $( this ).data( "button" );
          			setTimeout(function() {
          				inst.refresh();
          			}, 1 );
          		});
          	},
          	radioGroup = function( radio ) {
          		var name = radio.name,
          			form = radio.form,
          			radios = $( [] );
          		if ( name ) {
          			if ( form ) {
          				radios = $( form ).find( "[name='" + name + "']" );
          			} else {
          				radios = $( "[name='" + name + "']", radio.ownerDocument )
          					.filter(function() {
          						return !this.form;
          					});
          			}
          		}
          		return radios;
          	};
          
          $.widget( "ui.button", {
          	options: {
          		disabled: null,
          		text: true,
          		label: null,
          		icons: {
          			primary: null,
          			secondary: null
          		}
          	},
          	_create: function() {
          		this.element.closest( "form" )
          			.unbind( "reset.button" )
          			.bind( "reset.button", formResetHandler );
          
          		if ( typeof this.options.disabled !== "boolean" ) {
          			this.options.disabled = this.element.attr( "disabled" );
          		}
          
          		this._determineButtonType();
          		this.hasTitle = !!this.buttonElement.attr( "title" );
          
          		var self = this,
          			options = this.options,
          			toggleButton = this.type === "checkbox" || this.type === "radio",
          			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
          			focusClass = "ui-state-focus";
          
          		if ( options.label === null ) {
          			options.label = this.buttonElement.html();
          		}
          
          		if ( this.element.is( ":disabled" ) ) {
          			options.disabled = true;
          		}
          
          		this.buttonElement
          			.addClass( baseClasses )
          			.attr( "role", "button" )
          			.bind( "mouseenter.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).addClass( "ui-state-hover" );
          				if ( this === lastActive ) {
          					$( this ).addClass( "ui-state-active" );
          				}
          			})
          			.bind( "mouseleave.button", function() {
          				if ( options.disabled ) {
          					return;
          				}
          				$( this ).removeClass( hoverClass );
          			})
          			.bind( "focus.button", function() {
          				// no need to check disabled, focus won't be triggered anyway
          				$( this ).addClass( focusClass );
          			})
          			.bind( "blur.button", function() {
          				$( this ).removeClass( focusClass );
          			});
          
          		if ( toggleButton ) {
          			this.element.bind( "change.button", function() {
          				self.refresh();
          			});
          		}
          
          		if ( this.type === "checkbox" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).toggleClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
          			});
          		} else if ( this.type === "radio" ) {
          			this.buttonElement.bind( "click.button", function() {
          				if ( options.disabled ) {
          					return false;
          				}
          				$( this ).addClass( "ui-state-active" );
          				self.buttonElement.attr( "aria-pressed", true );
          
          				var radio = self.element[ 0 ];
          				radioGroup( radio )
          					.not( radio )
          					.map(function() {
          						return $( this ).button( "widget" )[ 0 ];
          					})
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			});
          		} else {
          			this.buttonElement
          				.bind( "mousedown.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).addClass( "ui-state-active" );
          					lastActive = this;
          					$( document ).one( "mouseup", function() {
          						lastActive = null;
          					});
          				})
          				.bind( "mouseup.button", function() {
          					if ( options.disabled ) {
          						return false;
          					}
          					$( this ).removeClass( "ui-state-active" );
          				})
          				.bind( "keydown.button", function(event) {
          					if ( options.disabled ) {
          						return false;
          					}
          					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
          						$( this ).addClass( "ui-state-active" );
          					}
          				})
          				.bind( "keyup.button", function() {
          					$( this ).removeClass( "ui-state-active" );
          				});
          
          			if ( this.buttonElement.is("a") ) {
          				this.buttonElement.keyup(function(event) {
          					if ( event.keyCode === $.ui.keyCode.SPACE ) {
          						// TODO pass through original event correctly (just as 2nd argument doesn't work)
          						$( this ).click();
          					}
          				});
          			}
          		}
          
          		// TODO: pull out $.Widget's handling for the disabled option into
          		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
          		// be overridden by individual plugins
          		this._setOption( "disabled", options.disabled );
          	},
          
          	_determineButtonType: function() {
          		
          		if ( this.element.is(":checkbox") ) {
          			this.type = "checkbox";
          		} else {
          			if ( this.element.is(":radio") ) {
          				this.type = "radio";
          			} else {
          				if ( this.element.is("input") ) {
          					this.type = "input";
          				} else {
          					this.type = "button";
          				}
          			}
          		}
          		
          		if ( this.type === "checkbox" || this.type === "radio" ) {
          			// we don't search against the document in case the element
          			// is disconnected from the DOM
          			this.buttonElement = this.element.parents().last()
          				.find( "label[for=" + this.element.attr("id") + "]" );
          			this.element.addClass( "ui-helper-hidden-accessible" );
          
          			var checked = this.element.is( ":checked" );
          			if ( checked ) {
          				this.buttonElement.addClass( "ui-state-active" );
          			}
          			this.buttonElement.attr( "aria-pressed", checked );
          		} else {
          			this.buttonElement = this.element;
          		}
          	},
          
          	widget: function() {
          		return this.buttonElement;
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-helper-hidden-accessible" );
          		this.buttonElement
          			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
          			.removeAttr( "role" )
          			.removeAttr( "aria-pressed" )
          			.html( this.buttonElement.find(".ui-button-text").html() );
          
          		if ( !this.hasTitle ) {
          			this.buttonElement.removeAttr( "title" );
          		}
          
          		$.Widget.prototype.destroy.call( this );
          	},
          
          	_setOption: function( key, value ) {
          		$.Widget.prototype._setOption.apply( this, arguments );
          		if ( key === "disabled" ) {
          			if ( value ) {
          				this.element.attr( "disabled", true );
          			} else {
          				this.element.removeAttr( "disabled" );
          			}
          		}
          		this._resetButton();
          	},
          
          	refresh: function() {
          		var isDisabled = this.element.is( ":disabled" );
          		if ( isDisabled !== this.options.disabled ) {
          			this._setOption( "disabled", isDisabled );
          		}
          		if ( this.type === "radio" ) {
          			radioGroup( this.element[0] ).each(function() {
          				if ( $( this ).is( ":checked" ) ) {
          					$( this ).button( "widget" )
          						.addClass( "ui-state-active" )
          						.attr( "aria-pressed", true );
          				} else {
          					$( this ).button( "widget" )
          						.removeClass( "ui-state-active" )
          						.attr( "aria-pressed", false );
          				}
          			});
          		} else if ( this.type === "checkbox" ) {
          			if ( this.element.is( ":checked" ) ) {
          				this.buttonElement
          					.addClass( "ui-state-active" )
          					.attr( "aria-pressed", true );
          			} else {
          				this.buttonElement
          					.removeClass( "ui-state-active" )
          					.attr( "aria-pressed", false );
          			}
          		}
          	},
          
          	_resetButton: function() {
          		if ( this.type === "input" ) {
          			if ( this.options.label ) {
          				this.element.val( this.options.label );
          			}
          			return;
          		}
          		var buttonElement = this.buttonElement.removeClass( typeClasses ),
          			buttonText = $( "<span></span>" )
          				.addClass( "ui-button-text" )
          				.html( this.options.label )
          				.appendTo( buttonElement.empty() )
          				.text(),
          			icons = this.options.icons,
          			multipleIcons = icons.primary && icons.secondary;
          		if ( icons.primary || icons.secondary ) {
          			buttonElement.addClass( "ui-button-text-icon" +
          				( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
          			if ( icons.primary ) {
          				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
          			}
          			if ( icons.secondary ) {
          				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
          			}
          			if ( !this.options.text ) {
          				buttonElement
          					.addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
          					.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
          				if ( !this.hasTitle ) {
          					buttonElement.attr( "title", buttonText );
          				}
          			}
          		} else {
          			buttonElement.addClass( "ui-button-text-only" );
          		}
          	}
          });
          
          $.widget( "ui.buttonset", {
          	_create: function() {
          		this.element.addClass( "ui-buttonset" );
          	},
          	
          	_init: function() {
          		this.refresh();
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "disabled" ) {
          			this.buttons.button( "option", key, value );
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          	
          	refresh: function() {
          		this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
          			.filter( ":ui-button" )
          				.button( "refresh" )
          			.end()
          			.not( ":ui-button" )
          				.button()
          			.end()
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
          				.filter( ":visible" )
          					.filter( ":first" )
          						.addClass( "ui-corner-left" )
          					.end()
          					.filter( ":last" )
          						.addClass( "ui-corner-right" )
          					.end()
          				.end()
          			.end();
          	},
          
          	destroy: function() {
          		this.element.removeClass( "ui-buttonset" );
          		this.buttons
          			.map(function() {
          				return $( this ).button( "widget" )[ 0 ];
          			})
          				.removeClass( "ui-corner-left ui-corner-right" )
          			.end()
          			.button( "destroy" );
          
          		$.Widget.prototype.destroy.call( this );
          	}
          });
          
          }( jQuery ) );
          /*
           * jQuery UI Datepicker 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Datepicker
           *
           * Depends:
           *	jquery.ui.core.js
           */
          (function( $, undefined ) {
          
          $.extend($.ui, { datepicker: { version: "1.8.6" } });
          
          var PROP_NAME = 'datepicker';
          var dpuuid = new Date().getTime();
          
          /* Date picker manager.
             Use the singleton instance of this class, $.datepicker, to interact with the date picker.
             Settings for (groups of) date pickers are maintained in an instance object,
             allowing multiple different settings on the same page. */
          
          function Datepicker() {
          	this.debug = false; // Change this to true to start debugging
          	this._curInst = null; // The current instance in use
          	this._keyEvent = false; // If the last event was a key event
          	this._disabledInputs = []; // List of date picker inputs that have been disabled
          	this._datepickerShowing = false; // True if the popup picker is showing , false if not
          	this._inDialog = false; // True if showing within a "dialog", false if not
          	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
          	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
          	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
          	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
          	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
          	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
          	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
          	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
          	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
          	this.regional = []; // Available regional settings, indexed by language code
          	this.regional[''] = { // Default regional settings
          		closeText: 'Done', // Display text for close link
          		prevText: 'Prev', // Display text for previous month link
          		nextText: 'Next', // Display text for next month link
          		currentText: 'Today', // Display text for current month link
          		monthNames: ['January','February','March','April','May','June',
          			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
          		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
          		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
          		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
          		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
          		weekHeader: 'Wk', // Column header for week of the year
          		dateFormat: 'mm/dd/yy', // See format options on parseDate
          		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
          		isRTL: false, // True if right-to-left language, false if left-to-right
          		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
          		yearSuffix: '' // Additional text to append to the year in the month headers
          	};
          	this._defaults = { // Global defaults for all the date picker instances
          		showOn: 'focus', // 'focus' for popup on focus,
          			// 'button' for trigger button, or 'both' for either
          		showAnim: 'fadeIn', // Name of jQuery animation for popup
          		showOptions: {}, // Options for enhanced animations
          		defaultDate: null, // Used when field is blank: actual date,
          			// +/-number for offset from today, null for today
          		appendText: '', // Display text following the input box, e.g. showing the format
          		buttonText: '...', // Text for trigger button
          		buttonImage: '', // URL for trigger button image
          		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
          		hideIfNoPrevNext: false, // True to hide next/previous month links
          			// if not applicable, false to just disable them
          		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
          		gotoCurrent: false, // True if today link goes back to current selection instead
          		changeMonth: false, // True if month can be selected directly, false if only prev/next
          		changeYear: false, // True if year can be selected directly, false if only prev/next
          		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
          			// either relative to today's year (-nn:+nn), relative to currently displayed year
          			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
          		showOtherMonths: false, // True to show dates in other months, false to leave blank
          		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
          		showWeek: false, // True to show week of the year, false to not show it
          		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
          			// takes a Date and returns the number of the week for it
          		shortYearCutoff: '+10', // Short year values < this are in the current century,
          			// > this are in the previous century,
          			// string value starting with '+' for current year + value
          		minDate: null, // The earliest selectable date, or null for no limit
          		maxDate: null, // The latest selectable date, or null for no limit
          		duration: 'fast', // Duration of display/closure
          		beforeShowDay: null, // Function that takes a date and returns an array with
          			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
          			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
          		beforeShow: null, // Function that takes an input field and
          			// returns a set of custom settings for the date picker
          		onSelect: null, // Define a callback function when a date is selected
          		onChangeMonthYear: null, // Define a callback function when the month or year is changed
          		onClose: null, // Define a callback function when the datepicker is closed
          		numberOfMonths: 1, // Number of months to show at a time
          		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
          		stepMonths: 1, // Number of months to step back/forward
          		stepBigMonths: 12, // Number of months to step back/forward for the big links
          		altField: '', // Selector for an alternate field to store selected dates into
          		altFormat: '', // The date format to use for the alternate field
          		constrainInput: true, // The input is constrained by the current date format
          		showButtonPanel: false, // True to show button panel, false to not show it
          		autoSize: false // True to size the input for the date format, false to leave as is
          	};
          	$.extend(this._defaults, this.regional['']);
          	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
          }
          
          $.extend(Datepicker.prototype, {
          	/* Class name added to elements to indicate already configured with a date picker. */
          	markerClassName: 'hasDatepicker',
          
          	/* Debug logging (if enabled). */
          	log: function () {
          		if (this.debug)
          			console.log.apply('', arguments);
          	},
          	
          	// TODO rename to "widget" when switching to widget factory
          	_widgetDatepicker: function() {
          		return this.dpDiv;
          	},
          
          	/* Override the default settings for all instances of the date picker.
          	   @param  settings  object - the new settings to use as defaults (anonymous object)
          	   @return the manager object */
          	setDefaults: function(settings) {
          		extendRemove(this._defaults, settings || {});
          		return this;
          	},
          
          	/* Attach the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span
          	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
          	_attachDatepicker: function(target, settings) {
          		// check for settings on the control itself - in namespace 'date:'
          		var inlineSettings = null;
          		for (var attrName in this._defaults) {
          			var attrValue = target.getAttribute('date:' + attrName);
          			if (attrValue) {
          				inlineSettings = inlineSettings || {};
          				try {
          					inlineSettings[attrName] = eval(attrValue);
          				} catch (err) {
          					inlineSettings[attrName] = attrValue;
          				}
          			}
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		var inline = (nodeName == 'div' || nodeName == 'span');
          		if (!target.id) {
          			this.uuid += 1;
          			target.id = 'dp' + this.uuid;
          		}
          		var inst = this._newInst($(target), inline);
          		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
          		if (nodeName == 'input') {
          			this._connectDatepicker(target, inst);
          		} else if (inline) {
          			this._inlineDatepicker(target, inst);
          		}
          	},
          
          	/* Create a new instance object. */
          	_newInst: function(target, inline) {
          		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
          		return {id: id, input: target, // associated target
          			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
          			drawMonth: 0, drawYear: 0, // month being drawn
          			inline: inline, // is datepicker inline or not
          			dpDiv: (!inline ? this.dpDiv : // presentation div
          			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
          	},
          
          	/* Attach the date picker to an input field. */
          	_connectDatepicker: function(target, inst) {
          		var input = $(target);
          		inst.append = $([]);
          		inst.trigger = $([]);
          		if (input.hasClass(this.markerClassName))
          			return;
          		this._attachments(input, inst);
          		input.addClass(this.markerClassName).keydown(this._doKeyDown).
          			keypress(this._doKeyPress).keyup(this._doKeyUp).
          			bind("setData.datepicker", function(event, key, value) {
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key) {
          				return this._get(inst, key);
          			});
          		this._autoSize(inst);
          		$.data(target, PROP_NAME, inst);
          	},
          
          	/* Make attachments based on settings. */
          	_attachments: function(input, inst) {
          		var appendText = this._get(inst, 'appendText');
          		var isRTL = this._get(inst, 'isRTL');
          		if (inst.append)
          			inst.append.remove();
          		if (appendText) {
          			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
          			input[isRTL ? 'before' : 'after'](inst.append);
          		}
          		input.unbind('focus', this._showDatepicker);
          		if (inst.trigger)
          			inst.trigger.remove();
          		var showOn = this._get(inst, 'showOn');
          		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
          			input.focus(this._showDatepicker);
          		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
          			var buttonText = this._get(inst, 'buttonText');
          			var buttonImage = this._get(inst, 'buttonImage');
          			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
          				$('<img/>').addClass(this._triggerClass).
          					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
          				$('<button type="button"></button>').addClass(this._triggerClass).
          					html(buttonImage == '' ? buttonText : $('<img/>').attr(
          					{ src:buttonImage, alt:buttonText, title:buttonText })));
          			input[isRTL ? 'before' : 'after'](inst.trigger);
          			inst.trigger.click(function() {
          				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
          					$.datepicker._hideDatepicker();
          				else
          					$.datepicker._showDatepicker(input[0]);
          				return false;
          			});
          		}
          	},
          
          	/* Apply the maximum length for the date format. */
          	_autoSize: function(inst) {
          		if (this._get(inst, 'autoSize') && !inst.inline) {
          			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
          			var dateFormat = this._get(inst, 'dateFormat');
          			if (dateFormat.match(/[DM]/)) {
          				var findMax = function(names) {
          					var max = 0;
          					var maxI = 0;
          					for (var i = 0; i < names.length; i++) {
          						if (names[i].length > max) {
          							max = names[i].length;
          							maxI = i;
          						}
          					}
          					return maxI;
          				};
          				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
          					'monthNames' : 'monthNamesShort'))));
          				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
          					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
          			}
          			inst.input.attr('size', this._formatDate(inst, date).length);
          		}
          	},
          
          	/* Attach an inline date picker to a div. */
          	_inlineDatepicker: function(target, inst) {
          		var divSpan = $(target);
          		if (divSpan.hasClass(this.markerClassName))
          			return;
          		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
          			bind("setData.datepicker", function(event, key, value){
          				inst.settings[key] = value;
          			}).bind("getData.datepicker", function(event, key){
          				return this._get(inst, key);
          			});
          		$.data(target, PROP_NAME, inst);
          		this._setDate(inst, this._getDefaultDate(inst), true);
          		this._updateDatepicker(inst);
          		this._updateAlternate(inst);
          	},
          
          	/* Pop-up the date picker in a "dialog" box.
          	   @param  input     element - ignored
          	   @param  date      string or Date - the initial date to display
          	   @param  onSelect  function - the function to call when a date is selected
          	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
          	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
          	                     event - with x/y coordinates or
          	                     leave empty for default (screen centre)
          	   @return the manager object */
          	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
          		var inst = this._dialogInst; // internal instance
          		if (!inst) {
          			this.uuid += 1;
          			var id = 'dp' + this.uuid;
          			this._dialogInput = $('<input type="text" id="' + id +
          				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
          			this._dialogInput.keydown(this._doKeyDown);
          			$('body').append(this._dialogInput);
          			inst = this._dialogInst = this._newInst(this._dialogInput, false);
          			inst.settings = {};
          			$.data(this._dialogInput[0], PROP_NAME, inst);
          		}
          		extendRemove(inst.settings, settings || {});
          		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
          		this._dialogInput.val(date);
          
          		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
          		if (!this._pos) {
          			var browserWidth = document.documentElement.clientWidth;
          			var browserHeight = document.documentElement.clientHeight;
          			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
          			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
          			this._pos = // should use actual width/height below
          				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
          		}
          
          		// move input on screen for focus, but hidden behind dialog
          		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
          		inst.settings.onSelect = onSelect;
          		this._inDialog = true;
          		this.dpDiv.addClass(this._dialogClass);
          		this._showDatepicker(this._dialogInput[0]);
          		if ($.blockUI)
          			$.blockUI(this.dpDiv);
          		$.data(this._dialogInput[0], PROP_NAME, inst);
          		return this;
          	},
          
          	/* Detach a datepicker from its control.
          	   @param  target    element - the target input field or division or span */
          	_destroyDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		$.removeData(target, PROP_NAME);
          		if (nodeName == 'input') {
          			inst.append.remove();
          			inst.trigger.remove();
          			$target.removeClass(this.markerClassName).
          				unbind('focus', this._showDatepicker).
          				unbind('keydown', this._doKeyDown).
          				unbind('keypress', this._doKeyPress).
          				unbind('keyup', this._doKeyUp);
          		} else if (nodeName == 'div' || nodeName == 'span')
          			$target.removeClass(this.markerClassName).empty();
          	},
          
          	/* Enable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_enableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = false;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = false; }).end().
          				filter('img').css({opacity: '1.0', cursor: ''});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().removeClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          	},
          
          	/* Disable the date picker to a jQuery selection.
          	   @param  target    element - the target input field or division or span */
          	_disableDatepicker: function(target) {
          		var $target = $(target);
          		var inst = $.data(target, PROP_NAME);
          		if (!$target.hasClass(this.markerClassName)) {
          			return;
          		}
          		var nodeName = target.nodeName.toLowerCase();
          		if (nodeName == 'input') {
          			target.disabled = true;
          			inst.trigger.filter('button').
          				each(function() { this.disabled = true; }).end().
          				filter('img').css({opacity: '0.5', cursor: 'default'});
          		}
          		else if (nodeName == 'div' || nodeName == 'span') {
          			var inline = $target.children('.' + this._inlineClass);
          			inline.children().addClass('ui-state-disabled');
          		}
          		this._disabledInputs = $.map(this._disabledInputs,
          			function(value) { return (value == target ? null : value); }); // delete entry
          		this._disabledInputs[this._disabledInputs.length] = target;
          	},
          
          	/* Is the first field in a jQuery collection disabled as a datepicker?
          	   @param  target    element - the target input field or division or span
          	   @return boolean - true if disabled, false if enabled */
          	_isDisabledDatepicker: function(target) {
          		if (!target) {
          			return false;
          		}
          		for (var i = 0; i < this._disabledInputs.length; i++) {
          			if (this._disabledInputs[i] == target)
          				return true;
          		}
          		return false;
          	},
          
          	/* Retrieve the instance data for the target control.
          	   @param  target  element - the target input field or division or span
          	   @return  object - the associated instance data
          	   @throws  error if a jQuery problem getting data */
          	_getInst: function(target) {
          		try {
          			return $.data(target, PROP_NAME);
          		}
          		catch (err) {
          			throw 'Missing instance data for this datepicker';
          		}
          	},
          
          	/* Update or retrieve the settings for a date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span
          	   @param  name    object - the new settings to update or
          	                   string - the name of the setting to change or retrieve,
          	                   when retrieving also 'all' for all instance settings or
          	                   'defaults' for all global defaults
          	   @param  value   any - the new value for the setting
          	                   (omit if above is an object or to retrieve a value) */
          	_optionDatepicker: function(target, name, value) {
          		var inst = this._getInst(target);
          		if (arguments.length == 2 && typeof name == 'string') {
          			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
          				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
          				this._get(inst, name)) : null));
          		}
          		var settings = name || {};
          		if (typeof name == 'string') {
          			settings = {};
          			settings[name] = value;
          		}
          		if (inst) {
          			if (this._curInst == inst) {
          				this._hideDatepicker();
          			}
          			var date = this._getDateDatepicker(target, true);
          			extendRemove(inst.settings, settings);
          			this._attachments($(target), inst);
          			this._autoSize(inst);
          			this._setDateDatepicker(target, date);
          			this._updateDatepicker(inst);
          		}
          	},
          
          	// change method deprecated
          	_changeDatepicker: function(target, name, value) {
          		this._optionDatepicker(target, name, value);
          	},
          
          	/* Redraw the date picker attached to an input field or division.
          	   @param  target  element - the target input field or division or span */
          	_refreshDatepicker: function(target) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._updateDatepicker(inst);
          		}
          	},
          
          	/* Set the dates for a jQuery selection.
          	   @param  target   element - the target input field or division or span
          	   @param  date     Date - the new date */
          	_setDateDatepicker: function(target, date) {
          		var inst = this._getInst(target);
          		if (inst) {
          			this._setDate(inst, date);
          			this._updateDatepicker(inst);
          			this._updateAlternate(inst);
          		}
          	},
          
          	/* Get the date(s) for the first entry in a jQuery selection.
          	   @param  target     element - the target input field or division or span
          	   @param  noDefault  boolean - true if no default date is to be used
          	   @return Date - the current date */
          	_getDateDatepicker: function(target, noDefault) {
          		var inst = this._getInst(target);
          		if (inst && !inst.inline)
          			this._setDateFromField(inst, noDefault);
          		return (inst ? this._getDate(inst) : null);
          	},
          
          	/* Handle keystrokes. */
          	_doKeyDown: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		var handled = true;
          		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
          		inst._keyEvent = true;
          		if ($.datepicker._datepickerShowing)
          			switch (event.keyCode) {
          				case 9: $.datepicker._hideDatepicker();
          						handled = false;
          						break; // hide on tab out
          				case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
          							add($('td.' + $.datepicker._currentClass, inst.dpDiv));
          						if (sel[0])
          							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
          						else
          							$.datepicker._hideDatepicker();
          						return false; // don't submit the form
          						break; // select the value on enter
          				case 27: $.datepicker._hideDatepicker();
          						break; // hide on escape
          				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							-$.datepicker._get(inst, 'stepBigMonths') :
          							-$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // previous month/year on page up/+ ctrl
          				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          							+$.datepicker._get(inst, 'stepBigMonths') :
          							+$.datepicker._get(inst, 'stepMonths')), 'M');
          						break; // next month/year on page down/+ ctrl
          				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // clear on ctrl or command +end
          				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
          						handled = event.ctrlKey || event.metaKey;
          						break; // current on ctrl or command +home
          				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// -1 day on ctrl or command +left
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									-$.datepicker._get(inst, 'stepBigMonths') :
          									-$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +left on Mac
          						break;
          				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // -1 week on ctrl or command +up
          				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
          						handled = event.ctrlKey || event.metaKey;
          						// +1 day on ctrl or command +right
          						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
          									+$.datepicker._get(inst, 'stepBigMonths') :
          									+$.datepicker._get(inst, 'stepMonths')), 'M');
          						// next month/year on alt +right
          						break;
          				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
          						handled = event.ctrlKey || event.metaKey;
          						break; // +1 week on ctrl or command +down
          				default: handled = false;
          			}
          		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
          			$.datepicker._showDatepicker(this);
          		else {
          			handled = false;
          		}
          		if (handled) {
          			event.preventDefault();
          			event.stopPropagation();
          		}
          	},
          
          	/* Filter entered characters - based on date format. */
          	_doKeyPress: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if ($.datepicker._get(inst, 'constrainInput')) {
          			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
          			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
          			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
          		}
          	},
          
          	/* Synchronise manual entry and field/alternate field. */
          	_doKeyUp: function(event) {
          		var inst = $.datepicker._getInst(event.target);
          		if (inst.input.val() != inst.lastVal) {
          			try {
          				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					(inst.input ? inst.input.val() : null),
          					$.datepicker._getFormatConfig(inst));
          				if (date) { // only if valid
          					$.datepicker._setDateFromField(inst);
          					$.datepicker._updateAlternate(inst);
          					$.datepicker._updateDatepicker(inst);
          				}
          			}
          			catch (event) {
          				$.datepicker.log(event);
          			}
          		}
          		return true;
          	},
          
          	/* Pop-up the date picker for a given input field.
          	   @param  input  element - the input field attached to the date picker or
          	                  event - if triggered by focus */
          	_showDatepicker: function(input) {
          		input = input.target || input;
          		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
          			input = $('input', input.parentNode)[0];
          		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
          			return;
          		var inst = $.datepicker._getInst(input);
          		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
          			$.datepicker._curInst.dpDiv.stop(true, true);
          		}
          		var beforeShow = $.datepicker._get(inst, 'beforeShow');
          		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
          		inst.lastVal = null;
          		$.datepicker._lastInput = input;
          		$.datepicker._setDateFromField(inst);
          		if ($.datepicker._inDialog) // hide cursor
          			input.value = '';
          		if (!$.datepicker._pos) { // position below input
          			$.datepicker._pos = $.datepicker._findPos(input);
          			$.datepicker._pos[1] += input.offsetHeight; // add the height
          		}
          		var isFixed = false;
          		$(input).parents().each(function() {
          			isFixed |= $(this).css('position') == 'fixed';
          			return !isFixed;
          		});
          		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
          			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
          			$.datepicker._pos[1] -= document.documentElement.scrollTop;
          		}
          		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
          		$.datepicker._pos = null;
          		// determine sizing offscreen
          		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
          		$.datepicker._updateDatepicker(inst);
          		// fix width for dynamic number of date pickers
          		// and adjust position before showing
          		offset = $.datepicker._checkOffset(inst, offset, isFixed);
          		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
          			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
          			left: offset.left + 'px', top: offset.top + 'px'});
          		if (!inst.inline) {
          			var showAnim = $.datepicker._get(inst, 'showAnim');
          			var duration = $.datepicker._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._datepickerShowing = true;
          				var borders = $.datepicker._getBorders(inst.dpDiv);
          				inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
          					css({left: -borders[0], top: -borders[1],
          						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
          			};
          			inst.dpDiv.zIndex($(input).zIndex()+1);
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
          			if (!showAnim || !duration)
          				postProcess();
          			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
          				inst.input.focus();
          			$.datepicker._curInst = inst;
          		}
          	},
          
          	/* Generate the date picker content. */
          	_updateDatepicker: function(inst) {
          		var self = this;
          		var borders = $.datepicker._getBorders(inst.dpDiv);
          		inst.dpDiv.empty().append(this._generateHTML(inst))
          			.find('iframe.ui-datepicker-cover') // IE6- only
          				.css({left: -borders[0], top: -borders[1],
          					width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
          			.end()
          			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
          				.bind('mouseout', function(){
          					$(this).removeClass('ui-state-hover');
          					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
          					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
          				})
          				.bind('mouseover', function(){
          					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
          						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
          						$(this).addClass('ui-state-hover');
          						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
          						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
          					}
          				})
          			.end()
          			.find('.' + this._dayOverClass + ' a')
          				.trigger('mouseover')
          			.end();
          		var numMonths = this._getNumberOfMonths(inst);
          		var cols = numMonths[1];
          		var width = 17;
          		if (cols > 1)
          			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          		else
          			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
          		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
          			'Class']('ui-datepicker-multi');
          		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
          			'Class']('ui-datepicker-rtl');
          		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
          				inst.input.is(':visible') && !inst.input.is(':disabled'))
          			inst.input.focus();
          	},
          
          	/* Retrieve the size of left and top borders for an element.
          	   @param  elem  (jQuery object) the element of interest
          	   @return  (number[2]) the left and top borders */
          	_getBorders: function(elem) {
          		var convert = function(value) {
          			return {thin: 1, medium: 2, thick: 3}[value] || value;
          		};
          		return [parseFloat(convert(elem.css('border-left-width'))),
          			parseFloat(convert(elem.css('border-top-width')))];
          	},
          
          	/* Check positioning to remain on screen. */
          	_checkOffset: function(inst, offset, isFixed) {
          		var dpWidth = inst.dpDiv.outerWidth();
          		var dpHeight = inst.dpDiv.outerHeight();
          		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
          		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
          		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
          		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
          
          		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
          		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
          		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
          
          		// now check if datepicker is showing outside window viewport - move to a better place if so.
          		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
          			Math.abs(offset.left + dpWidth - viewWidth) : 0);
          		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
          			Math.abs(dpHeight + inputHeight) : 0);
          
          		return offset;
          	},
          
          	/* Find an object's position on the screen. */
          	_findPos: function(obj) {
          		var inst = this._getInst(obj);
          		var isRTL = this._get(inst, 'isRTL');
                  while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                      obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
                  }
                  var position = $(obj).offset();
          	    return [position.left, position.top];
          	},
          
          	/* Hide the date picker from view.
          	   @param  input  element - the input field attached to the date picker */
          	_hideDatepicker: function(input) {
          		var inst = this._curInst;
          		if (!inst || (input && inst != $.data(input, PROP_NAME)))
          			return;
          		if (this._datepickerShowing) {
          			var showAnim = this._get(inst, 'showAnim');
          			var duration = this._get(inst, 'duration');
          			var postProcess = function() {
          				$.datepicker._tidyDialog(inst);
          				this._curInst = null;
          			};
          			if ($.effects && $.effects[showAnim])
          				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
          			else
          				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
          					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
          			if (!showAnim)
          				postProcess();
          			var onClose = this._get(inst, 'onClose');
          			if (onClose)
          				onClose.apply((inst.input ? inst.input[0] : null),
          					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
          			this._datepickerShowing = false;
          			this._lastInput = null;
          			if (this._inDialog) {
          				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
          				if ($.blockUI) {
          					$.unblockUI();
          					$('body').append(this.dpDiv);
          				}
          			}
          			this._inDialog = false;
          		}
          	},
          
          	/* Tidy up after a dialog display. */
          	_tidyDialog: function(inst) {
          		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
          	},
          
          	/* Close date picker if clicked elsewhere. */
          	_checkExternalClick: function(event) {
          		if (!$.datepicker._curInst)
          			return;
          		var $target = $(event.target);
          		if ($target[0].id != $.datepicker._mainDivId &&
          				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
          				!$target.hasClass($.datepicker.markerClassName) &&
          				!$target.hasClass($.datepicker._triggerClass) &&
          				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
          			$.datepicker._hideDatepicker();
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustDate: function(id, offset, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		this._adjustInstDate(inst, offset +
          			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
          			period);
          		this._updateDatepicker(inst);
          	},
          
          	/* Action for current link. */
          	_gotoToday: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
          			inst.selectedDay = inst.currentDay;
          			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
          			inst.drawYear = inst.selectedYear = inst.currentYear;
          		}
          		else {
          			var date = new Date();
          			inst.selectedDay = date.getDate();
          			inst.drawMonth = inst.selectedMonth = date.getMonth();
          			inst.drawYear = inst.selectedYear = date.getFullYear();
          		}
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Action for selecting a new month/year. */
          	_selectMonthYear: function(id, select, period) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		inst._selectingMonthYear = false;
          		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
          		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
          			parseInt(select.options[select.selectedIndex].value,10);
          		this._notifyChange(inst);
          		this._adjustDate(target);
          	},
          
          	/* Restore input focus after not changing month/year. */
          	_clickMonthYear: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		if (inst.input && inst._selectingMonthYear) {
          			setTimeout(function() {
          				inst.input.focus();
          			}, 0);
          		}
          		inst._selectingMonthYear = !inst._selectingMonthYear;
          	},
          
          	/* Action for selecting a day. */
          	_selectDay: function(id, month, year, td) {
          		var target = $(id);
          		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
          			return;
          		}
          		var inst = this._getInst(target[0]);
          		inst.selectedDay = inst.currentDay = $('a', td).html();
          		inst.selectedMonth = inst.currentMonth = month;
          		inst.selectedYear = inst.currentYear = year;
          		this._selectDate(id, this._formatDate(inst,
          			inst.currentDay, inst.currentMonth, inst.currentYear));
          	},
          
          	/* Erase the input field and hide the date picker. */
          	_clearDate: function(id) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		this._selectDate(target, '');
          	},
          
          	/* Update the input field with the selected date. */
          	_selectDate: function(id, dateStr) {
          		var target = $(id);
          		var inst = this._getInst(target[0]);
          		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
          		if (inst.input)
          			inst.input.val(dateStr);
          		this._updateAlternate(inst);
          		var onSelect = this._get(inst, 'onSelect');
          		if (onSelect)
          			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
          		else if (inst.input)
          			inst.input.trigger('change'); // fire the change event
          		if (inst.inline)
          			this._updateDatepicker(inst);
          		else {
          			this._hideDatepicker();
          			this._lastInput = inst.input[0];
          			if (typeof(inst.input[0]) != 'object')
          				inst.input.focus(); // restore focus
          			this._lastInput = null;
          		}
          	},
          
          	/* Update any alternate field to synchronise with the main field. */
          	_updateAlternate: function(inst) {
          		var altField = this._get(inst, 'altField');
          		if (altField) { // update alternate field too
          			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
          			var date = this._getDate(inst);
          			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
          			$(altField).each(function() { $(this).val(dateStr); });
          		}
          	},
          
          	/* Set as beforeShowDay function to prevent selection of weekends.
          	   @param  date  Date - the date to customise
          	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
          	noWeekends: function(date) {
          		var day = date.getDay();
          		return [(day > 0 && day < 6), ''];
          	},
          
          	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
          	   @param  date  Date - the date to get the week for
          	   @return  number - the number of the week within the year that contains this date */
          	iso8601Week: function(date) {
          		var checkDate = new Date(date.getTime());
          		// Find Thursday of this week starting on Monday
          		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
          		var time = checkDate.getTime();
          		checkDate.setMonth(0); // Compare with Jan 1
          		checkDate.setDate(1);
          		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
          	},
          
          	/* Parse a string value into a date object.
          	   See formatDate below for the possible formats.
          
          	   @param  format    string - the expected format of the date
          	   @param  value     string - the date in the above format
          	   @param  settings  Object - attributes include:
          	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  Date - the extracted date value or null if value is blank */
          	parseDate: function (format, value, settings) {
          		if (format == null || value == null)
          			throw 'Invalid arguments';
          		value = (typeof value == 'object' ? value.toString() : value + '');
          		if (value == '')
          			return null;
          		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		var year = -1;
          		var month = -1;
          		var day = -1;
          		var doy = -1;
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Extract a number from the string value
          		var getNumber = function(match) {
          			lookAhead(match);
          			var size = (match == '@' ? 14 : (match == '!' ? 20 :
          				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
          			var digits = new RegExp('^\\d{1,' + size + '}');
          			var num = value.substring(iValue).match(digits);
          			if (!num)
          				throw 'Missing number at position ' + iValue;
          			iValue += num[0].length;
          			return parseInt(num[0], 10);
          		};
          		// Extract a name from the string value and convert to an index
          		var getName = function(match, shortNames, longNames) {
          			var names = (lookAhead(match) ? longNames : shortNames);
          			for (var i = 0; i < names.length; i++) {
          				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
          					iValue += names[i].length;
          					return i + 1;
          				}
          			}
          			throw 'Unknown name at position ' + iValue;
          		};
          		// Confirm that a literal character matches the string value
          		var checkLiteral = function() {
          			if (value.charAt(iValue) != format.charAt(iFormat))
          				throw 'Unexpected literal at position ' + iValue;
          			iValue++;
          		};
          		var iValue = 0;
          		for (var iFormat = 0; iFormat < format.length; iFormat++) {
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					checkLiteral();
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd':
          						day = getNumber('d');
          						break;
          					case 'D':
          						getName('D', dayNamesShort, dayNames);
          						break;
          					case 'o':
          						doy = getNumber('o');
          						break;
          					case 'm':
          						month = getNumber('m');
          						break;
          					case 'M':
          						month = getName('M', monthNamesShort, monthNames);
          						break;
          					case 'y':
          						year = getNumber('y');
          						break;
          					case '@':
          						var date = new Date(getNumber('@'));
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case '!':
          						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
          						year = date.getFullYear();
          						month = date.getMonth() + 1;
          						day = date.getDate();
          						break;
          					case "'":
          						if (lookAhead("'"))
          							checkLiteral();
          						else
          							literal = true;
          						break;
          					default:
          						checkLiteral();
          				}
          		}
          		if (year == -1)
          			year = new Date().getFullYear();
          		else if (year < 100)
          			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
          				(year <= shortYearCutoff ? 0 : -100);
          		if (doy > -1) {
          			month = 1;
          			day = doy;
          			do {
          				var dim = this._getDaysInMonth(year, month - 1);
          				if (day <= dim)
          					break;
          				month++;
          				day -= dim;
          			} while (true);
          		}
          		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
          		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
          			throw 'Invalid date'; // E.g. 31/02/*
          		return date;
          	},
          
          	/* Standard date formats. */
          	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
          	COOKIE: 'D, dd M yy',
          	ISO_8601: 'yy-mm-dd',
          	RFC_822: 'D, d M y',
          	RFC_850: 'DD, dd-M-y',
          	RFC_1036: 'D, d M y',
          	RFC_1123: 'D, d M yy',
          	RFC_2822: 'D, d M yy',
          	RSS: 'D, d M y', // RFC 822
          	TICKS: '!',
          	TIMESTAMP: '@',
          	W3C: 'yy-mm-dd', // ISO 8601
          
          	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
          		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
          
          	/* Format a date object into a string value.
          	   The format can be combinations of the following:
          	   d  - day of month (no leading zero)
          	   dd - day of month (two digit)
          	   o  - day of year (no leading zeros)
          	   oo - day of year (three digit)
          	   D  - day name short
          	   DD - day name long
          	   m  - month of year (no leading zero)
          	   mm - month of year (two digit)
          	   M  - month name short
          	   MM - month name long
          	   y  - year (two digit)
          	   yy - year (four digit)
          	   @ - Unix timestamp (ms since 01/01/1970)
          	   ! - Windows ticks (100ns since 01/01/0001)
          	   '...' - literal text
          	   '' - single quote
          
          	   @param  format    string - the desired format of the date
          	   @param  date      Date - the date value to format
          	   @param  settings  Object - attributes include:
          	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
          	                     dayNames         string[7] - names of the days from Sunday (optional)
          	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
          	                     monthNames       string[12] - names of the months (optional)
          	   @return  string - the date in the above format */
          	formatDate: function (format, date, settings) {
          		if (!date)
          			return '';
          		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
          		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
          		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
          		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		// Format a number, with leading zero if necessary
          		var formatNumber = function(match, value, len) {
          			var num = '' + value;
          			if (lookAhead(match))
          				while (num.length < len)
          					num = '0' + num;
          			return num;
          		};
          		// Format a name, short or long as requested
          		var formatName = function(match, value, shortNames, longNames) {
          			return (lookAhead(match) ? longNames[value] : shortNames[value]);
          		};
          		var output = '';
          		var literal = false;
          		if (date)
          			for (var iFormat = 0; iFormat < format.length; iFormat++) {
          				if (literal)
          					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          						literal = false;
          					else
          						output += format.charAt(iFormat);
          				else
          					switch (format.charAt(iFormat)) {
          						case 'd':
          							output += formatNumber('d', date.getDate(), 2);
          							break;
          						case 'D':
          							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
          							break;
          						case 'o':
          							output += formatNumber('o',
          								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
          							break;
          						case 'm':
          							output += formatNumber('m', date.getMonth() + 1, 2);
          							break;
          						case 'M':
          							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
          							break;
          						case 'y':
          							output += (lookAhead('y') ? date.getFullYear() :
          								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
          							break;
          						case '@':
          							output += date.getTime();
          							break;
          						case '!':
          							output += date.getTime() * 10000 + this._ticksTo1970;
          							break;
          						case "'":
          							if (lookAhead("'"))
          								output += "'";
          							else
          								literal = true;
          							break;
          						default:
          							output += format.charAt(iFormat);
          					}
          			}
          		return output;
          	},
          
          	/* Extract all possible characters from the date format. */
          	_possibleChars: function (format) {
          		var chars = '';
          		var literal = false;
          		// Check whether a format character is doubled
          		var lookAhead = function(match) {
          			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
          			if (matches)
          				iFormat++;
          			return matches;
          		};
          		for (var iFormat = 0; iFormat < format.length; iFormat++)
          			if (literal)
          				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
          					literal = false;
          				else
          					chars += format.charAt(iFormat);
          			else
          				switch (format.charAt(iFormat)) {
          					case 'd': case 'm': case 'y': case '@':
          						chars += '0123456789';
          						break;
          					case 'D': case 'M':
          						return null; // Accept anything
          					case "'":
          						if (lookAhead("'"))
          							chars += "'";
          						else
          							literal = true;
          						break;
          					default:
          						chars += format.charAt(iFormat);
          				}
          		return chars;
          	},
          
          	/* Get a setting value, defaulting if necessary. */
          	_get: function(inst, name) {
          		return inst.settings[name] !== undefined ?
          			inst.settings[name] : this._defaults[name];
          	},
          
          	/* Parse existing date and initialise date picker. */
          	_setDateFromField: function(inst, noDefault) {
          		if (inst.input.val() == inst.lastVal) {
          			return;
          		}
          		var dateFormat = this._get(inst, 'dateFormat');
          		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
          		var date, defaultDate;
          		date = defaultDate = this._getDefaultDate(inst);
          		var settings = this._getFormatConfig(inst);
          		try {
          			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
          		} catch (event) {
          			this.log(event);
          			dates = (noDefault ? '' : dates);
          		}
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		inst.currentDay = (dates ? date.getDate() : 0);
          		inst.currentMonth = (dates ? date.getMonth() : 0);
          		inst.currentYear = (dates ? date.getFullYear() : 0);
          		this._adjustInstDate(inst);
          	},
          
          	/* Retrieve the default date shown on opening. */
          	_getDefaultDate: function(inst) {
          		return this._restrictMinMax(inst,
          			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
          	},
          
          	/* A date may be specified as an exact value or a relative one. */
          	_determineDate: function(inst, date, defaultDate) {
          		var offsetNumeric = function(offset) {
          			var date = new Date();
          			date.setDate(date.getDate() + offset);
          			return date;
          		};
          		var offsetString = function(offset) {
          			try {
          				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
          					offset, $.datepicker._getFormatConfig(inst));
          			}
          			catch (e) {
          				// Ignore
          			}
          			var date = (offset.toLowerCase().match(/^c/) ?
          				$.datepicker._getDate(inst) : null) || new Date();
          			var year = date.getFullYear();
          			var month = date.getMonth();
          			var day = date.getDate();
          			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
          			var matches = pattern.exec(offset);
          			while (matches) {
          				switch (matches[2] || 'd') {
          					case 'd' : case 'D' :
          						day += parseInt(matches[1],10); break;
          					case 'w' : case 'W' :
          						day += parseInt(matches[1],10) * 7; break;
          					case 'm' : case 'M' :
          						month += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          					case 'y': case 'Y' :
          						year += parseInt(matches[1],10);
          						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
          						break;
          				}
          				matches = pattern.exec(offset);
          			}
          			return new Date(year, month, day);
          		};
          		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
          			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
          		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
          		if (date) {
          			date.setHours(0);
          			date.setMinutes(0);
          			date.setSeconds(0);
          			date.setMilliseconds(0);
          		}
          		return this._daylightSavingAdjust(date);
          	},
          
          	/* Handle switch to/from daylight saving.
          	   Hours may be non-zero on daylight saving cut-over:
          	   > 12 when midnight changeover, but then cannot generate
          	   midnight datetime, so jump to 1AM, otherwise reset.
          	   @param  date  (Date) the date to check
          	   @return  (Date) the corrected date */
          	_daylightSavingAdjust: function(date) {
          		if (!date) return null;
          		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
          		return date;
          	},
          
          	/* Set the date(s) directly. */
          	_setDate: function(inst, date, noChange) {
          		var clear = !(date);
          		var origMonth = inst.selectedMonth;
          		var origYear = inst.selectedYear;
          		date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
          		inst.selectedDay = inst.currentDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
          		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
          			this._notifyChange(inst);
          		this._adjustInstDate(inst);
          		if (inst.input) {
          			inst.input.val(clear ? '' : this._formatDate(inst));
          		}
          	},
          
          	/* Retrieve the date(s) directly. */
          	_getDate: function(inst) {
          		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
          			this._daylightSavingAdjust(new Date(
          			inst.currentYear, inst.currentMonth, inst.currentDay)));
          			return startDate;
          	},
          
          	/* Generate the HTML for the current state of the date picker. */
          	_generateHTML: function(inst) {
          		var today = new Date();
          		today = this._daylightSavingAdjust(
          			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
          		var isRTL = this._get(inst, 'isRTL');
          		var showButtonPanel = this._get(inst, 'showButtonPanel');
          		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
          		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
          		var numMonths = this._getNumberOfMonths(inst);
          		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
          		var stepMonths = this._get(inst, 'stepMonths');
          		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
          		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
          			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		var drawMonth = inst.drawMonth - showCurrentAtPos;
          		var drawYear = inst.drawYear;
          		if (drawMonth < 0) {
          			drawMonth += 12;
          			drawYear--;
          		}
          		if (maxDate) {
          			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
          				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
          			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
          			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
          				drawMonth--;
          				if (drawMonth < 0) {
          					drawMonth = 11;
          					drawYear--;
          				}
          			}
          		}
          		inst.drawMonth = drawMonth;
          		inst.drawYear = drawYear;
          		var prevText = this._get(inst, 'prevText');
          		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
          			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
          		var nextText = this._get(inst, 'nextText');
          		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
          			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
          			this._getFormatConfig(inst)));
          		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
          			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
          			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
          			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
          		var currentText = this._get(inst, 'currentText');
          		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
          		currentText = (!navigationAsDateFormat ? currentText :
          			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
          		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
          		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
          			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
          			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
          			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
          		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
          		firstDay = (isNaN(firstDay) ? 0 : firstDay);
          		var showWeek = this._get(inst, 'showWeek');
          		var dayNames = this._get(inst, 'dayNames');
          		var dayNamesShort = this._get(inst, 'dayNamesShort');
          		var dayNamesMin = this._get(inst, 'dayNamesMin');
          		var monthNames = this._get(inst, 'monthNames');
          		var monthNamesShort = this._get(inst, 'monthNamesShort');
          		var beforeShowDay = this._get(inst, 'beforeShowDay');
          		var showOtherMonths = this._get(inst, 'showOtherMonths');
          		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
          		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
          		var defaultDate = this._getDefaultDate(inst);
          		var html = '';
          		for (var row = 0; row < numMonths[0]; row++) {
          			var group = '';
          			for (var col = 0; col < numMonths[1]; col++) {
          				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
          				var cornerClass = ' ui-corner-all';
          				var calender = '';
          				if (isMultiMonth) {
          					calender += '<div class="ui-datepicker-group';
          					if (numMonths[1] > 1)
          						switch (col) {
          							case 0: calender += ' ui-datepicker-group-first';
          								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
          							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
          								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
          							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
          						}
          					calender += '">';
          				}
          				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
          					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
          					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
          					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
          					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
          					'</div><table class="ui-datepicker-calendar"><thead>' +
          					'<tr>';
          				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
          				for (var dow = 0; dow < 7; dow++) { // days of the week
          					var day = (dow + firstDay) % 7;
          					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
          						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
          				}
          				calender += thead + '</tr></thead><tbody>';
          				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
          				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
          					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
          				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
          				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
          				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
          				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
          					calender += '<tr>';
          					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
          						this._get(inst, 'calculateWeek')(printDate) + '</td>');
          					for (var dow = 0; dow < 7; dow++) { // create date picker days
          						var daySettings = (beforeShowDay ?
          							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
          						var otherMonth = (printDate.getMonth() != drawMonth);
          						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
          							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
          						tbody += '<td class="' +
          							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
          							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
          							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
          							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
          							// or defaultDate is current printedDate and defaultDate is selectedDate
          							' ' + this._dayOverClass : '') + // highlight selected day
          							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
          							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
          							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
          							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
          							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
          							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
          							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
          							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
          							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
          							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
          							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
          							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
          							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
          						printDate.setDate(printDate.getDate() + 1);
          						printDate = this._daylightSavingAdjust(printDate);
          					}
          					calender += tbody + '</tr>';
          				}
          				drawMonth++;
          				if (drawMonth > 11) {
          					drawMonth = 0;
          					drawYear++;
          				}
          				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
          							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
          				group += calender;
          			}
          			html += group;
          		}
          		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
          			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
          		inst._keyEvent = false;
          		return html;
          	},
          
          	/* Generate the month and year header. */
          	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
          			secondary, monthNames, monthNamesShort) {
          		var changeMonth = this._get(inst, 'changeMonth');
          		var changeYear = this._get(inst, 'changeYear');
          		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
          		var html = '<div class="ui-datepicker-title">';
          		var monthHtml = '';
          		// month selection
          		if (secondary || !changeMonth)
          			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
          		else {
          			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
          			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
          			monthHtml += '<select class="ui-datepicker-month" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          			 	'>';
          			for (var month = 0; month < 12; month++) {
          				if ((!inMinYear || month >= minDate.getMonth()) &&
          						(!inMaxYear || month <= maxDate.getMonth()))
          					monthHtml += '<option value="' + month + '"' +
          						(month == drawMonth ? ' selected="selected"' : '') +
          						'>' + monthNamesShort[month] + '</option>';
          			}
          			monthHtml += '</select>';
          		}
          		if (!showMonthAfterYear)
          			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
          		// year selection
          		if (secondary || !changeYear)
          			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
          		else {
          			// determine range of years to display
          			var years = this._get(inst, 'yearRange').split(':');
          			var thisYear = new Date().getFullYear();
          			var determineYear = function(value) {
          				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
          					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
          					parseInt(value, 10)));
          				return (isNaN(year) ? thisYear : year);
          			};
          			var year = determineYear(years[0]);
          			var endYear = Math.max(year, determineYear(years[1] || ''));
          			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
          			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
          			html += '<select class="ui-datepicker-year" ' +
          				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
          				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
          				'>';
          			for (; year <= endYear; year++) {
          				html += '<option value="' + year + '"' +
          					(year == drawYear ? ' selected="selected"' : '') +
          					'>' + year + '</option>';
          			}
          			html += '</select>';
          		}
          		html += this._get(inst, 'yearSuffix');
          		if (showMonthAfterYear)
          			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
          		html += '</div>'; // Close datepicker_header
          		return html;
          	},
          
          	/* Adjust one of the date sub-fields. */
          	_adjustInstDate: function(inst, offset, period) {
          		var year = inst.drawYear + (period == 'Y' ? offset : 0);
          		var month = inst.drawMonth + (period == 'M' ? offset : 0);
          		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
          			(period == 'D' ? offset : 0);
          		var date = this._restrictMinMax(inst,
          			this._daylightSavingAdjust(new Date(year, month, day)));
          		inst.selectedDay = date.getDate();
          		inst.drawMonth = inst.selectedMonth = date.getMonth();
          		inst.drawYear = inst.selectedYear = date.getFullYear();
          		if (period == 'M' || period == 'Y')
          			this._notifyChange(inst);
          	},
          
          	/* Ensure a date is within any min/max bounds. */
          	_restrictMinMax: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		date = (minDate && date < minDate ? minDate : date);
          		date = (maxDate && date > maxDate ? maxDate : date);
          		return date;
          	},
          
          	/* Notify change of month/year. */
          	_notifyChange: function(inst) {
          		var onChange = this._get(inst, 'onChangeMonthYear');
          		if (onChange)
          			onChange.apply((inst.input ? inst.input[0] : null),
          				[inst.selectedYear, inst.selectedMonth + 1, inst]);
          	},
          
          	/* Determine the number of months to show. */
          	_getNumberOfMonths: function(inst) {
          		var numMonths = this._get(inst, 'numberOfMonths');
          		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
          	},
          
          	/* Determine the current maximum date - ensure no time components are set. */
          	_getMinMaxDate: function(inst, minMax) {
          		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
          	},
          
          	/* Find the number of days in a given month. */
          	_getDaysInMonth: function(year, month) {
          		return 32 - new Date(year, month, 32).getDate();
          	},
          
          	/* Find the day of the week of the first of a month. */
          	_getFirstDayOfMonth: function(year, month) {
          		return new Date(year, month, 1).getDay();
          	},
          
          	/* Determines if we should allow a "next/prev" month display change. */
          	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
          		var numMonths = this._getNumberOfMonths(inst);
          		var date = this._daylightSavingAdjust(new Date(curYear,
          			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
          		if (offset < 0)
          			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
          		return this._isInRange(inst, date);
          	},
          
          	/* Is the given date in the accepted range? */
          	_isInRange: function(inst, date) {
          		var minDate = this._getMinMaxDate(inst, 'min');
          		var maxDate = this._getMinMaxDate(inst, 'max');
          		return ((!minDate || date.getTime() >= minDate.getTime()) &&
          			(!maxDate || date.getTime() <= maxDate.getTime()));
          	},
          
          	/* Provide the configuration settings for formatting/parsing. */
          	_getFormatConfig: function(inst) {
          		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
          		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
          			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
          		return {shortYearCutoff: shortYearCutoff,
          			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
          			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
          	},
          
          	/* Format the given date for display. */
          	_formatDate: function(inst, day, month, year) {
          		if (!day) {
          			inst.currentDay = inst.selectedDay;
          			inst.currentMonth = inst.selectedMonth;
          			inst.currentYear = inst.selectedYear;
          		}
          		var date = (day ? (typeof day == 'object' ? day :
          			this._daylightSavingAdjust(new Date(year, month, day))) :
          			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
          		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
          	}
          });
          
          /* jQuery extend now ignores nulls! */
          function extendRemove(target, props) {
          	$.extend(target, props);
          	for (var name in props)
          		if (props[name] == null || props[name] == undefined)
          			target[name] = props[name];
          	return target;
          };
          
          /* Determine whether an object is an array. */
          function isArray(a) {
          	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
          		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
          };
          
          /* Invoke the datepicker functionality.
             @param  options  string - a command, optionally followed by additional parameters or
                              Object - settings for attaching new datepicker functionality
             @return  jQuery object */
          $.fn.datepicker = function(options){
          
          	/* Initialise the date picker. */
          	if (!$.datepicker.initialized) {
          		$(document).mousedown($.datepicker._checkExternalClick).
          			find('body').append($.datepicker.dpDiv);
          		$.datepicker.initialized = true;
          	}
          
          	var otherArgs = Array.prototype.slice.call(arguments, 1);
          	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
          		return $.datepicker['_' + options + 'Datepicker'].
          			apply($.datepicker, [this[0]].concat(otherArgs));
          	return this.each(function() {
          		typeof options == 'string' ?
          			$.datepicker['_' + options + 'Datepicker'].
          				apply($.datepicker, [this].concat(otherArgs)) :
          			$.datepicker._attachDatepicker(this, options);
          	});
          };
          
          $.datepicker = new Datepicker(); // singleton instance
          $.datepicker.initialized = false;
          $.datepicker.uuid = new Date().getTime();
          $.datepicker.version = "1.8.6";
          
          // Workaround for #4055
          // Add another global to avoid noConflict issues with inline event handlers
          window['DP_jQuery_' + dpuuid] = $;
          
          })(jQuery);
          /*
           * jQuery UI Dialog 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Dialog
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           *  jquery.ui.button.js
           *	jquery.ui.draggable.js
           *	jquery.ui.mouse.js
           *	jquery.ui.position.js
           *	jquery.ui.resizable.js
           */
          (function( $, undefined ) {
          
          var uiDialogClasses =
          		'ui-dialog ' +
          		'ui-widget ' +
          		'ui-widget-content ' +
          		'ui-corner-all ',
          	sizeRelatedOptions = {
          		buttons: true,
          		height: true,
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true,
          		width: true
          	},
          	resizableRelatedOptions = {
          		maxHeight: true,
          		maxWidth: true,
          		minHeight: true,
          		minWidth: true
          	};
          
          $.widget("ui.dialog", {
          	options: {
          		autoOpen: true,
          		buttons: {},
          		closeOnEscape: true,
          		closeText: 'close',
          		dialogClass: '',
          		draggable: true,
          		hide: null,
          		height: 'auto',
          		maxHeight: false,
          		maxWidth: false,
          		minHeight: 150,
          		minWidth: 150,
          		modal: false,
          		position: {
          			my: 'center',
          			at: 'center',
          			of: window,
          			collision: 'fit',
          			// ensure that the titlebar is never outside the document
          			using: function(pos) {
          				var topOffset = $(this).css(pos).offset().top;
          				if (topOffset < 0) {
          					$(this).css('top', pos.top - topOffset);
          				}
          			}
          		},
          		resizable: true,
          		show: null,
          		stack: true,
          		title: '',
          		width: 300,
          		zIndex: 1000
          	},
          
          	_create: function() {
          		this.originalTitle = this.element.attr('title');
          		// #5742 - .attr() might return a DOMElement
          		if ( typeof this.originalTitle !== "string" ) {
          			this.originalTitle = "";
          		}
          
          		this.options.title = this.options.title || this.originalTitle;
          		var self = this,
          			options = self.options,
          
          			title = options.title || '&#160;',
          			titleId = $.ui.dialog.getTitleId(self.element),
          
          			uiDialog = (self.uiDialog = $('<div></div>'))
          				.appendTo(document.body)
          				.hide()
          				.addClass(uiDialogClasses + options.dialogClass)
          				.css({
          					zIndex: options.zIndex
          				})
          				// setting tabIndex makes the div focusable
          				// setting outline to 0 prevents a border on focus in Mozilla
          				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
          					if (options.closeOnEscape && event.keyCode &&
          						event.keyCode === $.ui.keyCode.ESCAPE) {
          						
          						self.close(event);
          						event.preventDefault();
          					}
          				})
          				.attr({
          					role: 'dialog',
          					'aria-labelledby': titleId
          				})
          				.mousedown(function(event) {
          					self.moveToTop(false, event);
          				}),
          
          			uiDialogContent = self.element
          				.show()
          				.removeAttr('title')
          				.addClass(
          					'ui-dialog-content ' +
          					'ui-widget-content')
          				.appendTo(uiDialog),
          
          			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
          				.addClass(
          					'ui-dialog-titlebar ' +
          					'ui-widget-header ' +
          					'ui-corner-all ' +
          					'ui-helper-clearfix'
          				)
          				.prependTo(uiDialog),
          
          			uiDialogTitlebarClose = $('<a href="#"></a>')
          				.addClass(
          					'ui-dialog-titlebar-close ' +
          					'ui-corner-all'
          				)
          				.attr('role', 'button')
          				.hover(
          					function() {
          						uiDialogTitlebarClose.addClass('ui-state-hover');
          					},
          					function() {
          						uiDialogTitlebarClose.removeClass('ui-state-hover');
          					}
          				)
          				.focus(function() {
          					uiDialogTitlebarClose.addClass('ui-state-focus');
          				})
          				.blur(function() {
          					uiDialogTitlebarClose.removeClass('ui-state-focus');
          				})
          				.click(function(event) {
          					self.close(event);
          					return false;
          				})
          				.appendTo(uiDialogTitlebar),
          
          			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
          				.addClass(
          					'ui-icon ' +
          					'ui-icon-closethick'
          				)
          				.text(options.closeText)
          				.appendTo(uiDialogTitlebarClose),
          
          			uiDialogTitle = $('<span></span>')
          				.addClass('ui-dialog-title')
          				.attr('id', titleId)
          				.html(title)
          				.prependTo(uiDialogTitlebar);
          
          		//handling of deprecated beforeclose (vs beforeClose) option
          		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          		//TODO: remove in 1.9pre
          		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
          			options.beforeClose = options.beforeclose;
          		}
          
          		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
          
          		if (options.draggable && $.fn.draggable) {
          			self._makeDraggable();
          		}
          		if (options.resizable && $.fn.resizable) {
          			self._makeResizable();
          		}
          
          		self._createButtons(options.buttons);
          		self._isOpen = false;
          
          		if ($.fn.bgiframe) {
          			uiDialog.bgiframe();
          		}
          	},
          
          	_init: function() {
          		if ( this.options.autoOpen ) {
          			this.open();
          		}
          	},
          
          	destroy: function() {
          		var self = this;
          		
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.hide();
          		self.element
          			.unbind('.dialog')
          			.removeData('dialog')
          			.removeClass('ui-dialog-content ui-widget-content')
          			.hide().appendTo('body');
          		self.uiDialog.remove();
          
          		if (self.originalTitle) {
          			self.element.attr('title', self.originalTitle);
          		}
          
          		return self;
          	},
          
          	widget: function() {
          		return this.uiDialog;
          	},
          
          	close: function(event) {
          		var self = this,
          			maxZ;
          		
          		if (false === self._trigger('beforeClose', event)) {
          			return;
          		}
          
          		if (self.overlay) {
          			self.overlay.destroy();
          		}
          		self.uiDialog.unbind('keypress.ui-dialog');
          
          		self._isOpen = false;
          
          		if (self.options.hide) {
          			self.uiDialog.hide(self.options.hide, function() {
          				self._trigger('close', event);
          			});
          		} else {
          			self.uiDialog.hide();
          			self._trigger('close', event);
          		}
          
          		$.ui.dialog.overlay.resize();
          
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		if (self.options.modal) {
          			maxZ = 0;
          			$('.ui-dialog').each(function() {
          				if (this !== self.uiDialog[0]) {
          					maxZ = Math.max(maxZ, $(this).css('z-index'));
          				}
          			});
          			$.ui.dialog.maxZ = maxZ;
          		}
          
          		return self;
          	},
          
          	isOpen: function() {
          		return this._isOpen;
          	},
          
          	// the force parameter allows us to move modal dialogs to their correct
          	// position on open
          	moveToTop: function(force, event) {
          		var self = this,
          			options = self.options,
          			saveScroll;
          
          		if ((options.modal && !force) ||
          			(!options.stack && !options.modal)) {
          			return self._trigger('focus', event);
          		}
          
          		if (options.zIndex > $.ui.dialog.maxZ) {
          			$.ui.dialog.maxZ = options.zIndex;
          		}
          		if (self.overlay) {
          			$.ui.dialog.maxZ += 1;
          			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
          		}
          
          		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
          		//  http://ui.jquery.com/bugs/ticket/3193
          		saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
          		$.ui.dialog.maxZ += 1;
          		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
          		self.element.attr(saveScroll);
          		self._trigger('focus', event);
          
          		return self;
          	},
          
          	open: function() {
          		if (this._isOpen) { return; }
          
          		var self = this,
          			options = self.options,
          			uiDialog = self.uiDialog;
          
          		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
          		self._size();
          		self._position(options.position);
          		uiDialog.show(options.show);
          		self.moveToTop(true);
          
          		// prevent tabbing out of modal dialogs
          		if (options.modal) {
          			uiDialog.bind('keypress.ui-dialog', function(event) {
          				if (event.keyCode !== $.ui.keyCode.TAB) {
          					return;
          				}
          
          				var tabbables = $(':tabbable', this),
          					first = tabbables.filter(':first'),
          					last  = tabbables.filter(':last');
          
          				if (event.target === last[0] && !event.shiftKey) {
          					first.focus(1);
          					return false;
          				} else if (event.target === first[0] && event.shiftKey) {
          					last.focus(1);
          					return false;
          				}
          			});
          		}
          
          		// set focus to the first tabbable element in the content area or the first button
          		// if there are no tabbable elements, set focus on the dialog itself
          		$(self.element.find(':tabbable').get().concat(
          			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
          				uiDialog.get()))).eq(0).focus();
          
          		self._isOpen = true;
          		self._trigger('open');
          
          		return self;
          	},
          
          	_createButtons: function(buttons) {
          		var self = this,
          			hasButtons = false,
          			uiDialogButtonPane = $('<div></div>')
          				.addClass(
          					'ui-dialog-buttonpane ' +
          					'ui-widget-content ' +
          					'ui-helper-clearfix'
          				),
          			uiButtonSet = $( "<div></div>" )
          				.addClass( "ui-dialog-buttonset" )
          				.appendTo( uiDialogButtonPane );
          
          		// if we already have a button pane, remove it
          		self.uiDialog.find('.ui-dialog-buttonpane').remove();
          
          		if (typeof buttons === 'object' && buttons !== null) {
          			$.each(buttons, function() {
          				return !(hasButtons = true);
          			});
          		}
          		if (hasButtons) {
          			$.each(buttons, function(name, props) {
          				props = $.isFunction( props ) ?
          					{ click: props, text: name } :
          					props;
          				var button = $('<button type="button"></button>')
          					.attr( props, true )
          					.unbind('click')
          					.click(function() {
          						props.click.apply(self.element[0], arguments);
          					})
          					.appendTo(uiButtonSet);
          				if ($.fn.button) {
          					button.button();
          				}
          			});
          			uiDialogButtonPane.appendTo(self.uiDialog);
          		}
          	},
          
          	_makeDraggable: function() {
          		var self = this,
          			options = self.options,
          			doc = $(document),
          			heightBeforeDrag;
          
          		function filteredUi(ui) {
          			return {
          				position: ui.position,
          				offset: ui.offset
          			};
          		}
          
          		self.uiDialog.draggable({
          			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
          			handle: '.ui-dialog-titlebar',
          			containment: 'document',
          			start: function(event, ui) {
          				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
          				$(this).height($(this).height()).addClass("ui-dialog-dragging");
          				self._trigger('dragStart', event, filteredUi(ui));
          			},
          			drag: function(event, ui) {
          				self._trigger('drag', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				options.position = [ui.position.left - doc.scrollLeft(),
          					ui.position.top - doc.scrollTop()];
          				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
          				self._trigger('dragStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		});
          	},
          
          	_makeResizable: function(handles) {
          		handles = (handles === undefined ? this.options.resizable : handles);
          		var self = this,
          			options = self.options,
          			// .ui-resizable has position: relative defined in the stylesheet
          			// but dialogs have to use absolute or fixed positioning
          			position = self.uiDialog.css('position'),
          			resizeHandles = (typeof handles === 'string' ?
          				handles	:
          				'n,e,s,w,se,sw,ne,nw'
          			);
          
          		function filteredUi(ui) {
          			return {
          				originalPosition: ui.originalPosition,
          				originalSize: ui.originalSize,
          				position: ui.position,
          				size: ui.size
          			};
          		}
          
          		self.uiDialog.resizable({
          			cancel: '.ui-dialog-content',
          			containment: 'document',
          			alsoResize: self.element,
          			maxWidth: options.maxWidth,
          			maxHeight: options.maxHeight,
          			minWidth: options.minWidth,
          			minHeight: self._minHeight(),
          			handles: resizeHandles,
          			start: function(event, ui) {
          				$(this).addClass("ui-dialog-resizing");
          				self._trigger('resizeStart', event, filteredUi(ui));
          			},
          			resize: function(event, ui) {
          				self._trigger('resize', event, filteredUi(ui));
          			},
          			stop: function(event, ui) {
          				$(this).removeClass("ui-dialog-resizing");
          				options.height = $(this).height();
          				options.width = $(this).width();
          				self._trigger('resizeStop', event, filteredUi(ui));
          				$.ui.dialog.overlay.resize();
          			}
          		})
          		.css('position', position)
          		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
          	},
          
          	_minHeight: function() {
          		var options = this.options;
          
          		if (options.height === 'auto') {
          			return options.minHeight;
          		} else {
          			return Math.min(options.minHeight, options.height);
          		}
          	},
          
          	_position: function(position) {
          		var myAt = [],
          			offset = [0, 0],
          			isVisible;
          
          		if (position) {
          			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
          	//		if (typeof position == 'string' || $.isArray(position)) {
          	//			myAt = $.isArray(position) ? position : position.split(' ');
          
          			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
          				myAt = position.split ? position.split(' ') : [position[0], position[1]];
          				if (myAt.length === 1) {
          					myAt[1] = myAt[0];
          				}
          
          				$.each(['left', 'top'], function(i, offsetPosition) {
          					if (+myAt[i] === myAt[i]) {
          						offset[i] = myAt[i];
          						myAt[i] = offsetPosition;
          					}
          				});
          
          				position = {
          					my: myAt.join(" "),
          					at: myAt.join(" "),
          					offset: offset.join(" ")
          				};
          			} 
          
          			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
          		} else {
          			position = $.ui.dialog.prototype.options.position;
          		}
          
          		// need to show the dialog to get the actual offset in the position plugin
          		isVisible = this.uiDialog.is(':visible');
          		if (!isVisible) {
          			this.uiDialog.show();
          		}
          		this.uiDialog
          			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
          			.css({ top: 0, left: 0 })
          			.position(position);
          		if (!isVisible) {
          			this.uiDialog.hide();
          		}
          	},
          
          	_setOptions: function( options ) {
          		var self = this,
          			resizableOptions = {},
          			resize = false;
          
          		$.each( options, function( key, value ) {
          			self._setOption( key, value );
          			
          			if ( key in sizeRelatedOptions ) {
          				resize = true;
          			}
          			if ( key in resizableRelatedOptions ) {
          				resizableOptions[ key ] = value;
          			}
          		});
          
          		if ( resize ) {
          			this._size();
          		}
          		if ( this.uiDialog.is( ":data(resizable)" ) ) {
          			this.uiDialog.resizable( "option", resizableOptions );
          		}
          	},
          
          	_setOption: function(key, value){
          		var self = this,
          			uiDialog = self.uiDialog;
          
          		switch (key) {
          			//handling of deprecated beforeclose (vs beforeClose) option
          			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
          			//TODO: remove in 1.9pre
          			case "beforeclose":
          				key = "beforeClose";
          				break;
          			case "buttons":
          				self._createButtons(value);
          				break;
          			case "closeText":
          				// ensure that we always pass a string
          				self.uiDialogTitlebarCloseText.text("" + value);
          				break;
          			case "dialogClass":
          				uiDialog
          					.removeClass(self.options.dialogClass)
          					.addClass(uiDialogClasses + value);
          				break;
          			case "disabled":
          				if (value) {
          					uiDialog.addClass('ui-dialog-disabled');
          				} else {
          					uiDialog.removeClass('ui-dialog-disabled');
          				}
          				break;
          			case "draggable":
          				var isDraggable = uiDialog.is( ":data(draggable)" )
          				if ( isDraggable && !value ) {
          					uiDialog.draggable( "destroy" );
          				}
          				
          				if ( !isDraggable && value ) {
          					self._makeDraggable();
          				}
          				break;
          			case "position":
          				self._position(value);
          				break;
          			case "resizable":
          				// currently resizable, becoming non-resizable
          				var isResizable = uiDialog.is( ":data(resizable)" )
          				if (isResizable && !value) {
          					uiDialog.resizable('destroy');
          				}
          
          				// currently resizable, changing handles
          				if (isResizable && typeof value === 'string') {
          					uiDialog.resizable('option', 'handles', value);
          				}
          
          				// currently non-resizable, becoming resizable
          				if (!isResizable && value !== false) {
          					self._makeResizable(value);
          				}
          				break;
          			case "title":
          				// convert whatever was passed in o a string, for html() to not throw up
          				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
          				break;
          		}
          
          		$.Widget.prototype._setOption.apply(self, arguments);
          	},
          
          	_size: function() {
          		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
          		 * divs will both have width and height set, so we need to reset them
          		 */
          		var options = this.options,
          			nonContentHeight,
          			minContentHeight;
          
          		// reset content sizing
          		this.element.show().css({
          			width: 'auto',
          			minHeight: 0,
          			height: 0
          		});
          
          		if (options.minWidth > options.width) {
          			options.width = options.minWidth;
          		}
          
          		// reset wrapper sizing
          		// determine the height of all the non-content elements
          		nonContentHeight = this.uiDialog.css({
          				height: 'auto',
          				width: options.width
          			})
          			.height();
          		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
          		
          		if ( options.height === "auto" ) {
          			// only needed for IE6 support
          			if ( $.support.minHeight ) {
          				this.element.css({
          					minHeight: minContentHeight,
          					height: "auto"
          				});
          			} else {
          				this.uiDialog.show();
          				var autoHeight = this.element.css( "height", "auto" ).height();
          				this.uiDialog.hide();
          				this.element.height( Math.max( autoHeight, minContentHeight ) );
          			}
          		} else {
          			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
          		}
          
          		if (this.uiDialog.is(':data(resizable)')) {
          			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
          		}
          	}
          });
          
          $.extend($.ui.dialog, {
          	version: "1.8.6",
          
          	uuid: 0,
          	maxZ: 0,
          
          	getTitleId: function($el) {
          		var id = $el.attr('id');
          		if (!id) {
          			this.uuid += 1;
          			id = this.uuid;
          		}
          		return 'ui-dialog-title-' + id;
          	},
          
          	overlay: function(dialog) {
          		this.$el = $.ui.dialog.overlay.create(dialog);
          	}
          });
          
          $.extend($.ui.dialog.overlay, {
          	instances: [],
          	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
          	oldInstances: [],
          	maxZ: 0,
          	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
          		function(event) { return event + '.dialog-overlay'; }).join(' '),
          	create: function(dialog) {
          		if (this.instances.length === 0) {
          			// prevent use of anchors and inputs
          			// we use a setTimeout in case the overlay is created from an
          			// event that we're going to be cancelling (see #2804)
          			setTimeout(function() {
          				// handle $(el).dialog().dialog('close') (see #4065)
          				if ($.ui.dialog.overlay.instances.length) {
          					$(document).bind($.ui.dialog.overlay.events, function(event) {
          						// stop events if the z-index of the target is < the z-index of the overlay
          						// we cannot return true when we don't want to cancel the event (#3523)
          						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
          							return false;
          						}
          					});
          				}
          			}, 1);
          
          			// allow closing by pressing the escape key
          			$(document).bind('keydown.dialog-overlay', function(event) {
          				if (dialog.options.closeOnEscape && event.keyCode &&
          					event.keyCode === $.ui.keyCode.ESCAPE) {
          					
          					dialog.close(event);
          					event.preventDefault();
          				}
          			});
          
          			// handle window resize
          			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
          		}
          
          		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
          			.appendTo(document.body)
          			.css({
          				width: this.width(),
          				height: this.height()
          			});
          
          		if ($.fn.bgiframe) {
          			$el.bgiframe();
          		}
          
          		this.instances.push($el);
          		return $el;
          	},
          
          	destroy: function($el) {
          		this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
          
          		if (this.instances.length === 0) {
          			$([document, window]).unbind('.dialog-overlay');
          		}
          
          		$el.remove();
          		
          		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
          		var maxZ = 0;
          		$.each(this.instances, function() {
          			maxZ = Math.max(maxZ, this.css('z-index'));
          		});
          		this.maxZ = maxZ;
          	},
          
          	height: function() {
          		var scrollHeight,
          			offsetHeight;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollHeight = Math.max(
          				document.documentElement.scrollHeight,
          				document.body.scrollHeight
          			);
          			offsetHeight = Math.max(
          				document.documentElement.offsetHeight,
          				document.body.offsetHeight
          			);
          
          			if (scrollHeight < offsetHeight) {
          				return $(window).height() + 'px';
          			} else {
          				return scrollHeight + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).height() + 'px';
          		}
          	},
          
          	width: function() {
          		var scrollWidth,
          			offsetWidth;
          		// handle IE 6
          		if ($.browser.msie && $.browser.version < 7) {
          			scrollWidth = Math.max(
          				document.documentElement.scrollWidth,
          				document.body.scrollWidth
          			);
          			offsetWidth = Math.max(
          				document.documentElement.offsetWidth,
          				document.body.offsetWidth
          			);
          
          			if (scrollWidth < offsetWidth) {
          				return $(window).width() + 'px';
          			} else {
          				return scrollWidth + 'px';
          			}
          		// handle "good" browsers
          		} else {
          			return $(document).width() + 'px';
          		}
          	},
          
          	resize: function() {
          		/* If the dialog is draggable and the user drags it past the
          		 * right edge of the window, the document becomes wider so we
          		 * need to stretch the overlay. If the user then drags the
          		 * dialog back to the left, the document will become narrower,
          		 * so we need to shrink the overlay to the appropriate size.
          		 * This is handled by shrinking the overlay before setting it
          		 * to the full document size.
          		 */
          		var $overlays = $([]);
          		$.each($.ui.dialog.overlay.instances, function() {
          			$overlays = $overlays.add(this);
          		});
          
          		$overlays.css({
          			width: 0,
          			height: 0
          		}).css({
          			width: $.ui.dialog.overlay.width(),
          			height: $.ui.dialog.overlay.height()
          		});
          	}
          });
          
          $.extend($.ui.dialog.overlay.prototype, {
          	destroy: function() {
          		$.ui.dialog.overlay.destroy(this.$el);
          	}
          });
          
          }(jQuery));
          /*
           * jQuery UI Position 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Position
           */
          (function( $, undefined ) {
          
          $.ui = $.ui || {};
          
          var horizontalPositions = /left|center|right/,
          	verticalPositions = /top|center|bottom/,
          	center = "center",
          	_position = $.fn.position,
          	_offset = $.fn.offset;
          
          $.fn.position = function( options ) {
          	if ( !options || !options.of ) {
          		return _position.apply( this, arguments );
          	}
          
          	// make a copy, we don't want to modify arguments
          	options = $.extend( {}, options );
          
          	var target = $( options.of ),
          		targetElem = target[0],
          		collision = ( options.collision || "flip" ).split( " " ),
          		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
          		targetWidth,
          		targetHeight,
          		basePosition;
          
          	if ( targetElem.nodeType === 9 ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: 0, left: 0 };
          	// TODO: use $.isWindow() in 1.9
          	} else if ( targetElem.setTimeout ) {
          		targetWidth = target.width();
          		targetHeight = target.height();
          		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
          	} else if ( targetElem.preventDefault ) {
          		// force left top to allow flipping
          		options.at = "left top";
          		targetWidth = targetHeight = 0;
          		basePosition = { top: options.of.pageY, left: options.of.pageX };
          	} else {
          		targetWidth = target.outerWidth();
          		targetHeight = target.outerHeight();
          		basePosition = target.offset();
          	}
          
          	// force my and at to have valid horizontal and veritcal positions
          	// if a value is missing or invalid, it will be converted to center 
          	$.each( [ "my", "at" ], function() {
          		var pos = ( options[this] || "" ).split( " " );
          		if ( pos.length === 1) {
          			pos = horizontalPositions.test( pos[0] ) ?
          				pos.concat( [center] ) :
          				verticalPositions.test( pos[0] ) ?
          					[ center ].concat( pos ) :
          					[ center, center ];
          		}
          		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
          		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
          		options[ this ] = pos;
          	});
          
          	// normalize collision option
          	if ( collision.length === 1 ) {
          		collision[ 1 ] = collision[ 0 ];
          	}
          
          	// normalize offset option
          	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
          	if ( offset.length === 1 ) {
          		offset[ 1 ] = offset[ 0 ];
          	}
          	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
          
          	if ( options.at[0] === "right" ) {
          		basePosition.left += targetWidth;
          	} else if (options.at[0] === center ) {
          		basePosition.left += targetWidth / 2;
          	}
          
          	if ( options.at[1] === "bottom" ) {
          		basePosition.top += targetHeight;
          	} else if ( options.at[1] === center ) {
          		basePosition.top += targetHeight / 2;
          	}
          
          	basePosition.left += offset[ 0 ];
          	basePosition.top += offset[ 1 ];
          
          	return this.each(function() {
          		var elem = $( this ),
          			elemWidth = elem.outerWidth(),
          			elemHeight = elem.outerHeight(),
          			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
          			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
          			collisionWidth = elemWidth + marginLeft +
          				parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
          			collisionHeight = elemHeight + marginTop +
          				parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
          			position = $.extend( {}, basePosition ),
          			collisionPosition;
          
          		if ( options.my[0] === "right" ) {
          			position.left -= elemWidth;
          		} else if ( options.my[0] === center ) {
          			position.left -= elemWidth / 2;
          		}
          
          		if ( options.my[1] === "bottom" ) {
          			position.top -= elemHeight;
          		} else if ( options.my[1] === center ) {
          			position.top -= elemHeight / 2;
          		}
          
          		// prevent fractions (see #5280)
          		position.left = parseInt( position.left );
          		position.top = parseInt( position.top );
          
          		collisionPosition = {
          			left: position.left - marginLeft,
          			top: position.top - marginTop
          		};
          
          		$.each( [ "left", "top" ], function( i, dir ) {
          			if ( $.ui.position[ collision[i] ] ) {
          				$.ui.position[ collision[i] ][ dir ]( position, {
          					targetWidth: targetWidth,
          					targetHeight: targetHeight,
          					elemWidth: elemWidth,
          					elemHeight: elemHeight,
          					collisionPosition: collisionPosition,
          					collisionWidth: collisionWidth,
          					collisionHeight: collisionHeight,
          					offset: offset,
          					my: options.my,
          					at: options.at
          				});
          			}
          		});
          
          		if ( $.fn.bgiframe ) {
          			elem.bgiframe();
          		}
          		elem.offset( $.extend( position, { using: options.using } ) );
          	});
          };
          
          $.ui.position = {
          	fit: {
          		left: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
          			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
          		},
          		top: function( position, data ) {
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
          			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
          		}
          	},
          
          	flip: {
          		left: function( position, data ) {
          			if ( data.at[0] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
          				myOffset = data.my[ 0 ] === "left" ?
          					-data.elemWidth :
          					data.my[ 0 ] === "right" ?
          						data.elemWidth :
          						0,
          				atOffset = data.at[ 0 ] === "left" ?
          					data.targetWidth :
          					-data.targetWidth,
          				offset = -2 * data.offset[ 0 ];
          			position.left += data.collisionPosition.left < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		},
          		top: function( position, data ) {
          			if ( data.at[1] === center ) {
          				return;
          			}
          			var win = $( window ),
          				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
          				myOffset = data.my[ 1 ] === "top" ?
          					-data.elemHeight :
          					data.my[ 1 ] === "bottom" ?
          						data.elemHeight :
          						0,
          				atOffset = data.at[ 1 ] === "top" ?
          					data.targetHeight :
          					-data.targetHeight,
          				offset = -2 * data.offset[ 1 ];
          			position.top += data.collisionPosition.top < 0 ?
          				myOffset + atOffset + offset :
          				over > 0 ?
          					myOffset + atOffset + offset :
          					0;
          		}
          	}
          };
          
          // offset setter from jQuery 1.4
          if ( !$.offset.setOffset ) {
          	$.offset.setOffset = function( elem, options ) {
          		// set position first, in-case top/left are set even on static elem
          		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
          			elem.style.position = "relative";
          		}
          		var curElem   = $( elem ),
          			curOffset = curElem.offset(),
          			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
          			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
          			props     = {
          				top:  (options.top  - curOffset.top)  + curTop,
          				left: (options.left - curOffset.left) + curLeft
          			};
          		
          		if ( 'using' in options ) {
          			options.using.call( elem, props );
          		} else {
          			curElem.css( props );
          		}
          	};
          
          	$.fn.offset = function( options ) {
          		var elem = this[ 0 ];
          		if ( !elem || !elem.ownerDocument ) { return null; }
          		if ( options ) { 
          			return this.each(function() {
          				$.offset.setOffset( this, options );
          			});
          		}
          		return _offset.call( this );
          	};
          }
          
          }( jQuery ));
          /*
           * jQuery UI Progressbar 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Progressbar
           *
           * Depends:
           *   jquery.ui.core.js
           *   jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          $.widget( "ui.progressbar", {
          	options: {
          		value: 0
          	},
          
          	min: 0,
          	max: 100,
          
          	_create: function() {
          		this.element
          			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.attr({
          				role: "progressbar",
          				"aria-valuemin": this.min,
          				"aria-valuemax": this.max,
          				"aria-valuenow": this._value()
          			});
          
          		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
          			.appendTo( this.element );
          
          		this._refreshValue();
          	},
          
          	destroy: function() {
          		this.element
          			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
          			.removeAttr( "role" )
          			.removeAttr( "aria-valuemin" )
          			.removeAttr( "aria-valuemax" )
          			.removeAttr( "aria-valuenow" );
          
          		this.valueDiv.remove();
          
          		$.Widget.prototype.destroy.apply( this, arguments );
          	},
          
          	value: function( newValue ) {
          		if ( newValue === undefined ) {
          			return this._value();
          		}
          
          		this._setOption( "value", newValue );
          		return this;
          	},
          
          	_setOption: function( key, value ) {
          		if ( key === "value" ) {
          			this.options.value = value;
          			this._refreshValue();
          			this._trigger( "change" );
          			if ( this._value() === this.max ) {
          				this._trigger( "complete" );
          			}
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          	},
          
          	_value: function() {
          		var val = this.options.value;
          		// normalize invalid value
          		if ( typeof val !== "number" ) {
          			val = 0;
          		}
          		return Math.min( this.max, Math.max( this.min, val ) );
          	},
          
          	_refreshValue: function() {
          		var value = this.value();
          		this.valueDiv
          			.toggleClass( "ui-corner-right", value === this.max )
          			.width( value + "%" );
          		this.element.attr( "aria-valuenow", value );
          	}
          });
          
          $.extend( $.ui.progressbar, {
          	version: "1.8.6"
          });
          
          })( jQuery );
          /*
           * jQuery UI Slider 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Slider
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.mouse.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          // number of pages in a slider
          // (how many times can you page up/down to go through the whole range)
          var numPages = 5;
          
          $.widget( "ui.slider", $.ui.mouse, {
          
          	widgetEventPrefix: "slide",
          
          	options: {
          		animate: false,
          		distance: 0,
          		max: 100,
          		min: 0,
          		orientation: "horizontal",
          		range: false,
          		step: 1,
          		value: 0,
          		values: null
          	},
          
          	_create: function() {
          		var self = this,
          			o = this.options;
          
          		this._keySliding = false;
          		this._mouseSliding = false;
          		this._animateOff = true;
          		this._handleIndex = null;
          		this._detectOrientation();
          		this._mouseInit();
          
          		this.element
          			.addClass( "ui-slider" +
          				" ui-slider-" + this.orientation +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" );
          		
          		if ( o.disabled ) {
          			this.element.addClass( "ui-slider-disabled ui-disabled" );
          		}
          
          		this.range = $([]);
          
          		if ( o.range ) {
          			if ( o.range === true ) {
          				this.range = $( "<div></div>" );
          				if ( !o.values ) {
          					o.values = [ this._valueMin(), this._valueMin() ];
          				}
          				if ( o.values.length && o.values.length !== 2 ) {
          					o.values = [ o.values[0], o.values[0] ];
          				}
          			} else {
          				this.range = $( "<div></div>" );
          			}
          
          			this.range
          				.appendTo( this.element )
          				.addClass( "ui-slider-range" );
          
          			if ( o.range === "min" || o.range === "max" ) {
          				this.range.addClass( "ui-slider-range-" + o.range );
          			}
          
          			// note: this isn't the most fittingly semantic framework class for this element,
          			// but worked best visually with a variety of themes
          			this.range.addClass( "ui-widget-header" );
          		}
          
          		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
          			$( "<a href='#'></a>" )
          				.appendTo( this.element )
          				.addClass( "ui-slider-handle" );
          		}
          
          		if ( o.values && o.values.length ) {
          			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
          				$( "<a href='#'></a>" )
          					.appendTo( this.element )
          					.addClass( "ui-slider-handle" );
          			}
          		}
          
          		this.handles = $( ".ui-slider-handle", this.element )
          			.addClass( "ui-state-default" +
          				" ui-corner-all" );
          
          		this.handle = this.handles.eq( 0 );
          
          		this.handles.add( this.range ).filter( "a" )
          			.click(function( event ) {
          				event.preventDefault();
          			})
          			.hover(function() {
          				if ( !o.disabled ) {
          					$( this ).addClass( "ui-state-hover" );
          				}
          			}, function() {
          				$( this ).removeClass( "ui-state-hover" );
          			})
          			.focus(function() {
          				if ( !o.disabled ) {
          					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
          					$( this ).addClass( "ui-state-focus" );
          				} else {
          					$( this ).blur();
          				}
          			})
          			.blur(function() {
          				$( this ).removeClass( "ui-state-focus" );
          			});
          
          		this.handles.each(function( i ) {
          			$( this ).data( "index.ui-slider-handle", i );
          		});
          
          		this.handles
          			.keydown(function( event ) {
          				var ret = true,
          					index = $( this ).data( "index.ui-slider-handle" ),
          					allowed,
          					curVal,
          					newVal,
          					step;
          	
          				if ( self.options.disabled ) {
          					return;
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          					case $.ui.keyCode.END:
          					case $.ui.keyCode.PAGE_UP:
          					case $.ui.keyCode.PAGE_DOWN:
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						ret = false;
          						if ( !self._keySliding ) {
          							self._keySliding = true;
          							$( this ).addClass( "ui-state-active" );
          							allowed = self._start( event, index );
          							if ( allowed === false ) {
          								return;
          							}
          						}
          						break;
          				}
          	
          				step = self.options.step;
          				if ( self.options.values && self.options.values.length ) {
          					curVal = newVal = self.values( index );
          				} else {
          					curVal = newVal = self.value();
          				}
          	
          				switch ( event.keyCode ) {
          					case $.ui.keyCode.HOME:
          						newVal = self._valueMin();
          						break;
          					case $.ui.keyCode.END:
          						newVal = self._valueMax();
          						break;
          					case $.ui.keyCode.PAGE_UP:
          						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.PAGE_DOWN:
          						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
          						break;
          					case $.ui.keyCode.UP:
          					case $.ui.keyCode.RIGHT:
          						if ( curVal === self._valueMax() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal + step );
          						break;
          					case $.ui.keyCode.DOWN:
          					case $.ui.keyCode.LEFT:
          						if ( curVal === self._valueMin() ) {
          							return;
          						}
          						newVal = self._trimAlignValue( curVal - step );
          						break;
          				}
          	
          				self._slide( event, index, newVal );
          	
          				return ret;
          	
          			})
          			.keyup(function( event ) {
          				var index = $( this ).data( "index.ui-slider-handle" );
          	
          				if ( self._keySliding ) {
          					self._keySliding = false;
          					self._stop( event, index );
          					self._change( event, index );
          					$( this ).removeClass( "ui-state-active" );
          				}
          	
          			});
          
          		this._refreshValue();
          
          		this._animateOff = false;
          	},
          
          	destroy: function() {
          		this.handles.remove();
          		this.range.remove();
          
          		this.element
          			.removeClass( "ui-slider" +
          				" ui-slider-horizontal" +
          				" ui-slider-vertical" +
          				" ui-slider-disabled" +
          				" ui-widget" +
          				" ui-widget-content" +
          				" ui-corner-all" )
          			.removeData( "slider" )
          			.unbind( ".slider" );
          
          		this._mouseDestroy();
          
          		return this;
          	},
          
          	_mouseCapture: function( event ) {
          		var o = this.options,
          			position,
          			normValue,
          			distance,
          			closestHandle,
          			self,
          			index,
          			allowed,
          			offset,
          			mouseOverHandle;
          
          		if ( o.disabled ) {
          			return false;
          		}
          
          		this.elementSize = {
          			width: this.element.outerWidth(),
          			height: this.element.outerHeight()
          		};
          		this.elementOffset = this.element.offset();
          
          		position = { x: event.pageX, y: event.pageY };
          		normValue = this._normValueFromMouse( position );
          		distance = this._valueMax() - this._valueMin() + 1;
          		self = this;
          		this.handles.each(function( i ) {
          			var thisDistance = Math.abs( normValue - self.values(i) );
          			if ( distance > thisDistance ) {
          				distance = thisDistance;
          				closestHandle = $( this );
          				index = i;
          			}
          		});
          
          		// workaround for bug #3736 (if both handles of a range are at 0,
          		// the first is always used as the one with least distance,
          		// and moving it is obviously prevented by preventing negative ranges)
          		if( o.range === true && this.values(1) === o.min ) {
          			index += 1;
          			closestHandle = $( this.handles[index] );
          		}
          
          		allowed = this._start( event, index );
          		if ( allowed === false ) {
          			return false;
          		}
          		this._mouseSliding = true;
          
          		self._handleIndex = index;
          
          		closestHandle
          			.addClass( "ui-state-active" )
          			.focus();
          		
          		offset = closestHandle.offset();
          		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
          		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
          			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
          			top: event.pageY - offset.top -
          				( closestHandle.height() / 2 ) -
          				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
          				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
          				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
          		};
          
          		this._slide( event, index, normValue );
          		this._animateOff = true;
          		return true;
          	},
          
          	_mouseStart: function( event ) {
          		return true;
          	},
          
          	_mouseDrag: function( event ) {
          		var position = { x: event.pageX, y: event.pageY },
          			normValue = this._normValueFromMouse( position );
          		
          		this._slide( event, this._handleIndex, normValue );
          
          		return false;
          	},
          
          	_mouseStop: function( event ) {
          		this.handles.removeClass( "ui-state-active" );
          		this._mouseSliding = false;
          
          		this._stop( event, this._handleIndex );
          		this._change( event, this._handleIndex );
          
          		this._handleIndex = null;
          		this._clickOffset = null;
          		this._animateOff = false;
          
          		return false;
          	},
          	
          	_detectOrientation: function() {
          		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
          	},
          
          	_normValueFromMouse: function( position ) {
          		var pixelTotal,
          			pixelMouse,
          			percentMouse,
          			valueTotal,
          			valueMouse;
          
          		if ( this.orientation === "horizontal" ) {
          			pixelTotal = this.elementSize.width;
          			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
          		} else {
          			pixelTotal = this.elementSize.height;
          			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
          		}
          
          		percentMouse = ( pixelMouse / pixelTotal );
          		if ( percentMouse > 1 ) {
          			percentMouse = 1;
          		}
          		if ( percentMouse < 0 ) {
          			percentMouse = 0;
          		}
          		if ( this.orientation === "vertical" ) {
          			percentMouse = 1 - percentMouse;
          		}
          
          		valueTotal = this._valueMax() - this._valueMin();
          		valueMouse = this._valueMin() + percentMouse * valueTotal;
          
          		return this._trimAlignValue( valueMouse );
          	},
          
          	_start: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          		return this._trigger( "start", event, uiHash );
          	},
          
          	_slide: function( event, index, newVal ) {
          		var otherVal,
          			newValues,
          			allowed;
          
          		if ( this.options.values && this.options.values.length ) {
          			otherVal = this.values( index ? 0 : 1 );
          
          			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
          					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
          				) {
          				newVal = otherVal;
          			}
          
          			if ( newVal !== this.values( index ) ) {
          				newValues = this.values();
          				newValues[ index ] = newVal;
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal,
          					values: newValues
          				} );
          				otherVal = this.values( index ? 0 : 1 );
          				if ( allowed !== false ) {
          					this.values( index, newVal, true );
          				}
          			}
          		} else {
          			if ( newVal !== this.value() ) {
          				// A slide can be canceled by returning false from the slide callback
          				allowed = this._trigger( "slide", event, {
          					handle: this.handles[ index ],
          					value: newVal
          				} );
          				if ( allowed !== false ) {
          					this.value( newVal );
          				}
          			}
          		}
          	},
          
          	_stop: function( event, index ) {
          		var uiHash = {
          			handle: this.handles[ index ],
          			value: this.value()
          		};
          		if ( this.options.values && this.options.values.length ) {
          			uiHash.value = this.values( index );
          			uiHash.values = this.values();
          		}
          
          		this._trigger( "stop", event, uiHash );
          	},
          
          	_change: function( event, index ) {
          		if ( !this._keySliding && !this._mouseSliding ) {
          			var uiHash = {
          				handle: this.handles[ index ],
          				value: this.value()
          			};
          			if ( this.options.values && this.options.values.length ) {
          				uiHash.value = this.values( index );
          				uiHash.values = this.values();
          			}
          
          			this._trigger( "change", event, uiHash );
          		}
          	},
          
          	value: function( newValue ) {
          		if ( arguments.length ) {
          			this.options.value = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, 0 );
          		}
          
          		return this._value();
          	},
          
          	values: function( index, newValue ) {
          		var vals,
          			newValues,
          			i;
          
          		if ( arguments.length > 1 ) {
          			this.options.values[ index ] = this._trimAlignValue( newValue );
          			this._refreshValue();
          			this._change( null, index );
          		}
          
          		if ( arguments.length ) {
          			if ( $.isArray( arguments[ 0 ] ) ) {
          				vals = this.options.values;
          				newValues = arguments[ 0 ];
          				for ( i = 0; i < vals.length; i += 1 ) {
          					vals[ i ] = this._trimAlignValue( newValues[ i ] );
          					this._change( null, i );
          				}
          				this._refreshValue();
          			} else {
          				if ( this.options.values && this.options.values.length ) {
          					return this._values( index );
          				} else {
          					return this.value();
          				}
          			}
          		} else {
          			return this._values();
          		}
          	},
          
          	_setOption: function( key, value ) {
          		var i,
          			valsLength = 0;
          
          		if ( $.isArray( this.options.values ) ) {
          			valsLength = this.options.values.length;
          		}
          
          		$.Widget.prototype._setOption.apply( this, arguments );
          
          		switch ( key ) {
          			case "disabled":
          				if ( value ) {
          					this.handles.filter( ".ui-state-focus" ).blur();
          					this.handles.removeClass( "ui-state-hover" );
          					this.handles.attr( "disabled", "disabled" );
          					this.element.addClass( "ui-disabled" );
          				} else {
          					this.handles.removeAttr( "disabled" );
          					this.element.removeClass( "ui-disabled" );
          				}
          				break;
          			case "orientation":
          				this._detectOrientation();
          				this.element
          					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
          					.addClass( "ui-slider-" + this.orientation );
          				this._refreshValue();
          				break;
          			case "value":
          				this._animateOff = true;
          				this._refreshValue();
          				this._change( null, 0 );
          				this._animateOff = false;
          				break;
          			case "values":
          				this._animateOff = true;
          				this._refreshValue();
          				for ( i = 0; i < valsLength; i += 1 ) {
          					this._change( null, i );
          				}
          				this._animateOff = false;
          				break;
          		}
          	},
          
          	//internal value getter
          	// _value() returns value trimmed by min and max, aligned by step
          	_value: function() {
          		var val = this.options.value;
          		val = this._trimAlignValue( val );
          
          		return val;
          	},
          
          	//internal values getter
          	// _values() returns array of values trimmed by min and max, aligned by step
          	// _values( index ) returns single value trimmed by min and max, aligned by step
          	_values: function( index ) {
          		var val,
          			vals,
          			i;
          
          		if ( arguments.length ) {
          			val = this.options.values[ index ];
          			val = this._trimAlignValue( val );
          
          			return val;
          		} else {
          			// .slice() creates a copy of the array
          			// this copy gets trimmed by min and max and then returned
          			vals = this.options.values.slice();
          			for ( i = 0; i < vals.length; i+= 1) {
          				vals[ i ] = this._trimAlignValue( vals[ i ] );
          			}
          
          			return vals;
          		}
          	},
          	
          	// returns the step-aligned value that val is closest to, between (inclusive) min and max
          	_trimAlignValue: function( val ) {
          		if ( val < this._valueMin() ) {
          			return this._valueMin();
          		}
          		if ( val > this._valueMax() ) {
          			return this._valueMax();
          		}
          		var step = ( this.options.step > 0 ) ? this.options.step : 1,
          			valModStep = val % step,
          			alignValue = val - valModStep;
          
          		if ( Math.abs(valModStep) * 2 >= step ) {
          			alignValue += ( valModStep > 0 ) ? step : ( -step );
          		}
          
          		// Since JavaScript has problems with large floats, round
          		// the final value to 5 digits after the decimal point (see #4124)
          		return parseFloat( alignValue.toFixed(5) );
          	},
          
          	_valueMin: function() {
          		return this.options.min;
          	},
          
          	_valueMax: function() {
          		return this.options.max;
          	},
          	
          	_refreshValue: function() {
          		var oRange = this.options.range,
          			o = this.options,
          			self = this,
          			animate = ( !this._animateOff ) ? o.animate : false,
          			valPercent,
          			_set = {},
          			lastValPercent,
          			value,
          			valueMin,
          			valueMax;
          
          		if ( this.options.values && this.options.values.length ) {
          			this.handles.each(function( i, j ) {
          				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
          				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          				if ( self.options.range === true ) {
          					if ( self.orientation === "horizontal" ) {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					} else {
          						if ( i === 0 ) {
          							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
          						}
          						if ( i === 1 ) {
          							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
          						}
          					}
          				}
          				lastValPercent = valPercent;
          			});
          		} else {
          			value = this.value();
          			valueMin = this._valueMin();
          			valueMax = this._valueMax();
          			valPercent = ( valueMax !== valueMin ) ?
          					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
          					0;
          			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
          			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
          
          			if ( oRange === "min" && this.orientation === "horizontal" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "horizontal" ) {
          				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          			if ( oRange === "min" && this.orientation === "vertical" ) {
          				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
          			}
          			if ( oRange === "max" && this.orientation === "vertical" ) {
          				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
          			}
          		}
          	}
          
          });
          
          $.extend( $.ui.slider, {
          	version: "1.8.6"
          });
          
          }(jQuery));
          /*
           * jQuery UI Tabs 1.8.6
           *
           * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
           * Dual licensed under the MIT or GPL Version 2 licenses.
           * http://jquery.org/license
           *
           * http://docs.jquery.com/UI/Tabs
           *
           * Depends:
           *	jquery.ui.core.js
           *	jquery.ui.widget.js
           */
          (function( $, undefined ) {
          
          var tabId = 0,
          	listId = 0;
          
          function getNextTabId() {
          	return ++tabId;
          }
          
          function getNextListId() {
          	return ++listId;
          }
          
          $.widget( "ui.tabs", {
          	options: {
          		add: null,
          		ajaxOptions: null,
          		cache: false,
          		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
          		collapsible: false,
          		disable: null,
          		disabled: [],
          		enable: null,
          		event: "click",
          		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
          		idPrefix: "ui-tabs-",
          		load: null,
          		panelTemplate: "<div></div>",
          		remove: null,
          		select: null,
          		show: null,
          		spinner: "<em>Loading&#8230;</em>",
          		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
          	},
          
          	_create: function() {
          		this._tabify( true );
          	},
          
          	_setOption: function( key, value ) {
          		if ( key == "selected" ) {
          			if (this.options.collapsible && value == this.options.selected ) {
          				return;
          			}
          			this.select( value );
          		} else {
          			this.options[ key ] = value;
          			this._tabify();
          		}
          	},
          
          	_tabId: function( a ) {
          		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
          			this.options.idPrefix + getNextTabId();
          	},
          
          	_sanitizeSelector: function( hash ) {
          		// we need this because an id may contain a ":"
          		return hash.replace( /:/g, "\\:" );
          	},
          
          	_cookie: function() {
          		var cookie = this.cookie ||
          			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
          		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
          	},
          
          	_ui: function( tab, panel ) {
          		return {
          			tab: tab,
          			panel: panel,
          			index: this.anchors.index( tab )
          		};
          	},
          
          	_cleanup: function() {
          		// restore all former loading tabs labels
          		this.lis.filter( ".ui-state-processing" )
          			.removeClass( "ui-state-processing" )
          			.find( "span:data(label.tabs)" )
          				.each(function() {
          					var el = $( this );
          					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
          				});
          	},
          
          	_tabify: function( init ) {
          		var self = this,
          			o = this.options,
          			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
          
          		this.list = this.element.find( "ol,ul" ).eq( 0 );
          		this.lis = $( " > li:has(a[href])", this.list );
          		this.anchors = this.lis.map(function() {
          			return $( "a", this )[ 0 ];
          		});
          		this.panels = $( [] );
          
          		this.anchors.each(function( i, a ) {
          			var href = $( a ).attr( "href" );
          			// For dynamically created HTML that contains a hash as href IE < 8 expands
          			// such href to the full page url with hash and then misinterprets tab as ajax.
          			// Same consideration applies for an added tab with a fragment identifier
          			// since a[href=#fragment-identifier] does unexpectedly not match.
          			// Thus normalize href attribute...
          			var hrefBase = href.split( "#" )[ 0 ],
          				baseEl;
          			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
          				href = a.hash;
          				a.href = href;
          			}
          
          			// inline tab
          			if ( fragmentId.test( href ) ) {
          				self.panels = self.panels.add( self._sanitizeSelector( href ) );
          			// remote tab
          			// prevent loading the page itself if href is just "#"
          			} else if ( href && href !== "#" ) {
          				// required for restore on destroy
          				$.data( a, "href.tabs", href );
          
          				// TODO until #3808 is fixed strip fragment identifier from url
          				// (IE fails to load from such url)
          				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
          
          				var id = self._tabId( a );
          				a.href = "#" + id;
          				var $panel = $( "#" + id );
          				if ( !$panel.length ) {
          					$panel = $( o.panelTemplate )
          						.attr( "id", id )
          						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
          						.insertAfter( self.panels[ i - 1 ] || self.list );
          					$panel.data( "destroy.tabs", true );
          				}
          				self.panels = self.panels.add( $panel );
          			// invalid tab href
          			} else {
          				o.disabled.push( i );
          			}
          		});
          
          		// initialization from scratch
          		if ( init ) {
          			// attach necessary classes for styling
          			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
          			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          			this.lis.addClass( "ui-state-default ui-corner-top" );
          			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
          
          			// Selected tab
          			// use "selected" option or try to retrieve:
          			// 1. from fragment identifier in url
          			// 2. from cookie
          			// 3. from selected class attribute on <li>
          			if ( o.selected === undefined ) {
          				if ( location.hash ) {
          					this.anchors.each(function( i, a ) {
          						if ( a.hash == location.hash ) {
          							o.selected = i;
          							return false;
          						}
          					});
          				}
          				if ( typeof o.selected !== "number" && o.cookie ) {
          					o.selected = parseInt( self._cookie(), 10 );
          				}
          				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
          					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          				}
          				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
          			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
          				o.selected = -1;
          			}
          
          			// sanity check - default to first tab...
          			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
          				? o.selected
          				: 0;
          
          			// Take disabling tabs via class attribute from HTML
          			// into account and update option properly.
          			// A selected tab cannot become disabled.
          			o.disabled = $.unique( o.disabled.concat(
          				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
          					return self.lis.index( n );
          				})
          			) ).sort();
          
          			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
          				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
          			}
          
          			// highlight selected tab
          			this.panels.addClass( "ui-tabs-hide" );
          			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
          			// check for length avoids error when initializing empty list
          			if ( o.selected >= 0 && this.anchors.length ) {
          				$( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
          				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
          
          				// seems to be expected behavior that the show callback is fired
          				self.element.queue( "tabs", function() {
          					self._trigger( "show", null,
          						self._ui( self.anchors[ o.selected ], $( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
          				});
          
          				this.load( o.selected );
          			}
          
          			// clean up to avoid memory leaks in certain versions of IE 6
          			// TODO: namespace this event
          			$( window ).bind( "unload", function() {
          				self.lis.add( self.anchors ).unbind( ".tabs" );
          				self.lis = self.anchors = self.panels = null;
          			});
          		// update selected after add/remove
          		} else {
          			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
          		}
          
          		// update collapsible
          		// TODO: use .toggleClass()
          		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
          
          		// set or update cookie after init and add/remove respectively
          		if ( o.cookie ) {
          			this._cookie( o.selected, o.cookie );
          		}
          
          		// disable tabs
          		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
          			$( li )[ $.inArray( i, o.disabled ) != -1 &&
          				// TODO: use .toggleClass()
          				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
          		}
          
          		// reset cache if switching from cached to not cached
          		if ( o.cache === false ) {
          			this.anchors.removeData( "cache.tabs" );
          		}
          
          		// remove all handlers before, tabify may run on existing tabs after add or option change
          		this.lis.add( this.anchors ).unbind( ".tabs" );
          
          		if ( o.event !== "mouseover" ) {
          			var addState = function( state, el ) {
          				if ( el.is( ":not(.ui-state-disabled)" ) ) {
          					el.addClass( "ui-state-" + state );
          				}
          			};
          			var removeState = function( state, el ) {
          				el.removeClass( "ui-state-" + state );
          			};
          			this.lis.bind( "mouseover.tabs" , function() {
          				addState( "hover", $( this ) );
          			});
          			this.lis.bind( "mouseout.tabs", function() {
          				removeState( "hover", $( this ) );
          			});
          			this.anchors.bind( "focus.tabs", function() {
          				addState( "focus", $( this ).closest( "li" ) );
          			});
          			this.anchors.bind( "blur.tabs", function() {
          				removeState( "focus", $( this ).closest( "li" ) );
          			});
          		}
          
          		// set up animations
          		var hideFx, showFx;
          		if ( o.fx ) {
          			if ( $.isArray( o.fx ) ) {
          				hideFx = o.fx[ 0 ];
          				showFx = o.fx[ 1 ];
          			} else {
          				hideFx = showFx = o.fx;
          			}
          		}
          
          		// Reset certain styles left over from animation
          		// and prevent IE's ClearType bug...
          		function resetStyle( $el, fx ) {
          			$el.css( "display", "" );
          			if ( !$.support.opacity && fx.opacity ) {
          				$el[ 0 ].style.removeAttribute( "filter" );
          			}
          		}
          
          		// Show a tab...
          		var showTab = showFx
          			? function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
          					.animate( showFx, showFx.duration || "normal", function() {
          						resetStyle( $show, showFx );
          						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          					});
          			}
          			: function( clicked, $show ) {
          				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
          				$show.removeClass( "ui-tabs-hide" );
          				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
          			};
          
          		// Hide a tab, $show is optional...
          		var hideTab = hideFx
          			? function( clicked, $hide ) {
          				$hide.animate( hideFx, hideFx.duration || "normal", function() {
          					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          					$hide.addClass( "ui-tabs-hide" );
          					resetStyle( $hide, hideFx );
          					self.element.dequeue( "tabs" );
          				});
          			}
          			: function( clicked, $hide, $show ) {
          				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
          				$hide.addClass( "ui-tabs-hide" );
          				self.element.dequeue( "tabs" );
          			};
          
          		// attach tab event handler, unbind to avoid duplicates from former tabifying...
          		this.anchors.bind( o.event + ".tabs", function() {
          			var el = this,
          				$li = $(el).closest( "li" ),
          				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
          				$show = $( self._sanitizeSelector( el.hash ) );
          
          			// If tab is already selected and not collapsible or tab disabled or
          			// or is already loading or click callback returns false stop here.
          			// Check if click handler returns false last so that it is not executed
          			// for a disabled or loading tab!
          			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
          				$li.hasClass( "ui-state-disabled" ) ||
          				$li.hasClass( "ui-state-processing" ) ||
          				self.panels.filter( ":animated" ).length ||
          				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
          				this.blur();
          				return false;
          			}
          
          			o.selected = self.anchors.index( this );
          
          			self.abort();
          
          			// if tab may be closed
          			if ( o.collapsible ) {
          				if ( $li.hasClass( "ui-tabs-selected" ) ) {
          					o.selected = -1;
          
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					}).dequeue( "tabs" );
          
          					this.blur();
          					return false;
          				} else if ( !$hide.length ) {
          					if ( o.cookie ) {
          						self._cookie( o.selected, o.cookie );
          					}
          
          					self.element.queue( "tabs", function() {
          						showTab( el, $show );
          					});
          
          					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
          					self.load( self.anchors.index( this ) );
          
          					this.blur();
          					return false;
          				}
          			}
          
          			if ( o.cookie ) {
          				self._cookie( o.selected, o.cookie );
          			}
          
          			// show new tab
          			if ( $show.length ) {
          				if ( $hide.length ) {
          					self.element.queue( "tabs", function() {
          						hideTab( el, $hide );
          					});
          				}
          				self.element.queue( "tabs", function() {
          					showTab( el, $show );
          				});
          
          				self.load( self.anchors.index( this ) );
          			} else {
          				throw "jQuery UI Tabs: Mismatching fragment identifier.";
          			}
          
          			// Prevent IE from keeping other link focussed when using the back button
          			// and remove dotted border from clicked link. This is controlled via CSS
          			// in modern browsers; blur() removes focus from address bar in Firefox
          			// which can become a usability and annoying problem with tabs('rotate').
          			if ( $.browser.msie ) {
          				this.blur();
          			}
          		});
          
          		// disable click in any case
          		this.anchors.bind( "click.tabs", function(){
          			return false;
          		});
          	},
          
              _getIndex: function( index ) {
          		// meta-function to give users option to provide a href string instead of a numerical index.
          		// also sanitizes numerical indexes to valid values.
          		if ( typeof index == "string" ) {
          			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
          		}
          
          		return index;
          	},
          
          	destroy: function() {
          		var o = this.options;
          
          		this.abort();
          
          		this.element
          			.unbind( ".tabs" )
          			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
          			.removeData( "tabs" );
          
          		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
          
          		this.anchors.each(function() {
          			var href = $.data( this, "href.tabs" );
          			if ( href ) {
          				this.href = href;
          			}
          			var $this = $( this ).unbind( ".tabs" );
          			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
          				$this.removeData( prefix + ".tabs" );
          			});
          		});
          
          		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
          			if ( $.data( this, "destroy.tabs" ) ) {
          				$( this ).remove();
          			} else {
          				$( this ).removeClass([
          					"ui-state-default",
          					"ui-corner-top",
          					"ui-tabs-selected",
          					"ui-state-active",
          					"ui-state-hover",
          					"ui-state-focus",
          					"ui-state-disabled",
          					"ui-tabs-panel",
          					"ui-widget-content",
          					"ui-corner-bottom",
          					"ui-tabs-hide"
          				].join( " " ) );
          			}
          		});
          
          		if ( o.cookie ) {
          			this._cookie( null, o.cookie );
          		}
          
          		return this;
          	},
          
          	add: function( url, label, index ) {
          		if ( index === undefined ) {
          			index = this.anchors.length;
          		}
          
          		var self = this,
          			o = this.options,
          			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
          			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
          
          		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
          
          		// try to find an existing element before creating a new one
          		var $panel = $( "#" + id );
          		if ( !$panel.length ) {
          			$panel = $( o.panelTemplate )
          				.attr( "id", id )
          				.data( "destroy.tabs", true );
          		}
          		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
          
          		if ( index >= this.lis.length ) {
          			$li.appendTo( this.list );
          			$panel.appendTo( this.list[ 0 ].parentNode );
          		} else {
          			$li.insertBefore( this.lis[ index ] );
          			$panel.insertBefore( this.panels[ index ] );
          		}
          
          		o.disabled = $.map( o.disabled, function( n, i ) {
          			return n >= index ? ++n : n;
          		});
          
          		this._tabify();
          
          		if ( this.anchors.length == 1 ) {
          			o.selected = 0;
          			$li.addClass( "ui-tabs-selected ui-state-active" );
          			$panel.removeClass( "ui-tabs-hide" );
          			this.element.queue( "tabs", function() {
          				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
          			});
          
          			this.load( 0 );
          		}
          
          		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	remove: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options,
          			$li = this.lis.eq( index ).remove(),
          			$panel = this.panels.eq( index ).remove();
          
          		// If selected tab was removed focus tab to the right or
          		// in case the last tab was removed the tab to the left.
          		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
          			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
          		}
          
          		o.disabled = $.map(
          			$.grep( o.disabled, function(n, i) {
          				return n != index;
          			}),
          			function( n, i ) {
          				return n >= index ? --n : n;
          			});
          
          		this._tabify();
          
          		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
          		return this;
          	},
          
          	enable: function( index ) {
          		index = this._getIndex( index );
          		var o = this.options;
          		if ( $.inArray( index, o.disabled ) == -1 ) {
          			return;
          		}
          
          		this.lis.eq( index ).removeClass( "ui-state-disabled" );
          		o.disabled = $.grep( o.disabled, function( n, i ) {
          			return n != index;
          		});
          
          		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		return this;
          	},
          
          	disable: function( index ) {
          		index = this._getIndex( index );
          		var self = this, o = this.options;
          		// cannot disable already selected tab
          		if ( index != o.selected ) {
          			this.lis.eq( index ).addClass( "ui-state-disabled" );
          
          			o.disabled.push( index );
          			o.disabled.sort();
          
          			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
          		}
          
          		return this;
          	},
          
          	select: function( index ) {
          		index = this._getIndex( index );
          		if ( index == -1 ) {
          			if ( this.options.collapsible && this.options.selected != -1 ) {
          				index = this.options.selected;
          			} else {
          				return this;
          			}
          		}
          		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
          		return this;
          	},
          
          	load: function( index ) {
          		index = this._getIndex( index );
          		var self = this,
          			o = this.options,
          			a = this.anchors.eq( index )[ 0 ],
          			url = $.data( a, "load.tabs" );
          
          		this.abort();
          
          		// not remote or from cache
          		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
          			this.element.dequeue( "tabs" );
          			return;
          		}
          
          		// load remote from here on
          		this.lis.eq( index ).addClass( "ui-state-processing" );
          
          		if ( o.spinner ) {
          			var span = $( "span", a );
          			span.data( "label.tabs", span.html() ).html( o.spinner );
          		}
          
          		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
          			url: url,
          			success: function( r, s ) {
          				$( self._sanitizeSelector( a.hash ) ).html( r );
          
          				// take care of tab labels
          				self._cleanup();
          
          				if ( o.cache ) {
          					$.data( a, "cache.tabs", true );
          				}
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					o.ajaxOptions.success( r, s );
          				}
          				catch ( e ) {}
          			},
          			error: function( xhr, s, e ) {
          				// take care of tab labels
          				self._cleanup();
          
          				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
          				try {
          					// Passing index avoid a race condition when this method is
          					// called after the user has selected another tab.
          					// Pass the anchor that initiated this request allows
          					// loadError to manipulate the tab content panel via $(a.hash)
          					o.ajaxOptions.error( xhr, s, index, a );
          				}
          				catch ( e ) {}
          			}
          		} ) );
          
          		// last, so that load event is fired before show...
          		self.element.dequeue( "tabs" );
          
          		return this;
          	},
          
          	abort: function() {
          		// stop possibly running animations
          		this.element.queue( [] );
          		this.panels.stop( false, true );
          
          		// "tabs" queue must not contain more than two elements,
          		// which are the callbacks for the latest clicked tab...
          		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
          
          		// terminate pending requests from other tabs
          		if ( this.xhr ) {
          			this.xhr.abort();
          			delete this.xhr;
          		}
          
          		// take care of tab labels
          		this._cleanup();
          		return this;
          	},
          
          	url: function( index, url ) {
          		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
          		return this;
          	},
          
          	length: function() {
          		return this.anchors.length;
          	}
          });
          
          $.extend( $.ui.tabs, {
          	version: "1.8.6"
          });
          
          /*
           * Tabs Extensions
           */
          
          /*
           * Rotate
           */
          $.extend( $.ui.tabs.prototype, {
          	rotation: null,
          	rotate: function( ms, continuing ) {
          		var self = this,
          			o = this.options;
          
          		var rotate = self._rotate || ( self._rotate = function( e ) {
          			clearTimeout( self.rotation );
          			self.rotation = setTimeout(function() {
          				var t = o.selected;
          				self.select( ++t < self.anchors.length ? t : 0 );
          			}, ms );
          			
          			if ( e ) {
          				e.stopPropagation();
          			}
          		});
          
          		var stop = self._unrotate || ( self._unrotate = !continuing
          			? function(e) {
          				if (e.clientX) { // in case of a true click
          					self.rotate(null);
          				}
          			}
          			: function( e ) {
          				t = o.selected;
          				rotate();
          			});
          
          		// start rotation
          		if ( ms ) {
          			this.element.bind( "tabsshow", rotate );
          			this.anchors.bind( o.event + ".tabs", stop );
          			rotate();
          		// stop rotation
          		} else {
          			clearTimeout( self.rotation );
          			this.element.unbind( "tabsshow", rotate );
          			this.anchors.unbind( o.event + ".tabs", stop );
          			delete this._rotate;
          			delete this._unrotate;
          		}
          
          		return this;
          	}
          });
          
          })( jQuery );
          
          Evidence
          where
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        16. GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bSELECT\b and was detected 2 times, the first in the element starting with: "(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){v", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (368 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 93868
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"93868-1329845124000"
          Last-Modified: Tue, 21 Feb 2012 17:25:24 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (93868 bytes)
          /*! jQuery v1.7.1 jquery.com | jquery.org/license */
          (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
          f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.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(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
          {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
          Evidence
          select
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        17. GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSERNAME\b and was detected in the element starting with: "{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (368 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/jquery.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 93868
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"93868-1329845124000"
          Last-Modified: Tue, 21 Feb 2012 17:25:24 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (93868 bytes)
          /*! jQuery v1.7.1 jquery.com | jquery.org/license */
          (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
          f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.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(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
          {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
          Evidence
          username
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        18. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected in the element starting with: " // remove items from success list", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (397 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 37133
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"37133-1268175436000"
          Last-Modified: Tue, 09 Mar 2010 22:57:16 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (37133 bytes)
          /*
           * jQuery validation plug-in 1.7
           *
           * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
           * http://docs.jquery.com/Plugins/Validation
           *
           * Copyright (c) 2006 - 2008 Jörn Zaefferer
           *
           * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          $.extend($.fn, {
          	// http://docs.jquery.com/Plugins/Validation/validate
          	validate: function( options ) {
          
          		// if nothing is selected, return nothing; can't chain anyway
          		if (!this.length) {
          			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
          			return;
          		}
          
          		// check if a validator for this form was already created
          		var validator = $.data(this[0], 'validator');
          		if ( validator ) {
          			return validator;
          		}
          		
          		validator = new $.validator( options, this[0] );
          		$.data(this[0], 'validator', validator); 
          		
          		if ( validator.settings.onsubmit ) {
          		
          			// allow suppresing validation by adding a cancel class to the submit button
          			this.find("input, button").filter(".cancel").click(function() {
          				validator.cancelSubmit = true;
          			});
          			
          			// when a submitHandler is used, capture the submitting button
          			if (validator.settings.submitHandler) {
          				this.find("input, button").filter(":submit").click(function() {
          					validator.submitButton = this;
          				});
          			}
          		
          			// validate the form on submit
          			this.submit( function( event ) {
          				if ( validator.settings.debug )
          					// prevent form submit to be able to see console output
          					event.preventDefault();
          					
          				function handle() {
          					if ( validator.settings.submitHandler ) {
          						if (validator.submitButton) {
          							// insert a hidden input as a replacement for the missing submit button
          							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
          						}
          						validator.settings.submitHandler.call( validator, validator.currentForm );
          						if (validator.submitButton) {
          							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
          							hidden.remove();
          						}
          						return false;
          					}
          					return true;
          				}
          					
          				// prevent submit for invalid forms or custom submit handlers
          				if ( validator.cancelSubmit ) {
          					validator.cancelSubmit = false;
          					return handle();
          				}
          				if ( validator.form() ) {
          					if ( validator.pendingRequest ) {
          						validator.formSubmitted = true;
          						return false;
          					}
          					return handle();
          				} else {
          					validator.focusInvalid();
          					return false;
          				}
          			});
          		}
          		
          		return validator;
          	},
          	// http://docs.jquery.com/Plugins/Validation/valid
          	valid: function() {
                  if ( $(this[0]).is('form')) {
                      return this.validate().form();
                  } else {
                      var valid = true;
                      var validator = $(this[0].form).validate();
                      this.each(function() {
          				valid &= validator.element(this);
                      });
                      return valid;
                  }
              },
          	// attributes: space seperated list of attributes to retrieve and remove
          	removeAttrs: function(attributes) {
          		var result = {},
          			$element = this;
          		$.each(attributes.split(/\s/), function(index, value) {
          			result[value] = $element.attr(value);
          			$element.removeAttr(value);
          		});
          		return result;
          	},
          	// http://docs.jquery.com/Plugins/Validation/rules
          	rules: function(command, argument) {
          		var element = this[0];
          		
          		if (command) {
          			var settings = $.data(element.form, 'validator').settings;
          			var staticRules = settings.rules;
          			var existingRules = $.validator.staticRules(element);
          			switch(command) {
          			case "add":
          				$.extend(existingRules, $.validator.normalizeRule(argument));
          				staticRules[element.name] = existingRules;
          				if (argument.messages)
          					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
          				break;
          			case "remove":
          				if (!argument) {
          					delete staticRules[element.name];
          					return existingRules;
          				}
          				var filtered = {};
          				$.each(argument.split(/\s/), function(index, method) {
          					filtered[method] = existingRules[method];
          					delete existingRules[method];
          				});
          				return filtered;
          			}
          		}
          		
          		var data = $.validator.normalizeRules(
          		$.extend(
          			{},
          			$.validator.metadataRules(element),
          			$.validator.classRules(element),
          			$.validator.attributeRules(element),
          			$.validator.staticRules(element)
          		), element);
          		
          		// make sure required is at front
          		if (data.required) {
          			var param = data.required;
          			delete data.required;
          			data = $.extend({required: param}, data);
          		}
          		
          		return data;
          	}
          });
          
          // Custom selectors
          $.extend($.expr[":"], {
          	// http://docs.jquery.com/Plugins/Validation/blank
          	blank: function(a) {return !$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/filled
          	filled: function(a) {return !!$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/unchecked
          	unchecked: function(a) {return !a.checked;}
          });
          
          // constructor for validator
          $.validator = function( options, form ) {
          	this.settings = $.extend( true, {}, $.validator.defaults, options );
          	this.currentForm = form;
          	this.init();
          };
          
          $.validator.format = function(source, params) {
          	if ( arguments.length == 1 ) 
          		return function() {
          			var args = $.makeArray(arguments);
          			args.unshift(source);
          			return $.validator.format.apply( this, args );
          		};
          	if ( arguments.length > 2 && params.constructor != Array  ) {
          		params = $.makeArray(arguments).slice(1);
          	}
          	if ( params.constructor != Array ) {
          		params = [ params ];
          	}
          	$.each(params, function(i, n) {
          		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
          	});
          	return source;
          };
          
          $.extend($.validator, {
          	
          	defaults: {
          		messages: {},
          		groups: {},
          		rules: {},
          		errorClass: "error",
          		validClass: "valid",
          		errorElement: "label",
          		focusInvalid: true,
          		errorContainer: $( [] ),
          		errorLabelContainer: $( [] ),
          		onsubmit: true,
          		ignore: [],
          		ignoreTitle: false,
          		onfocusin: function(element) {
          			this.lastActive = element;
          				
          			// hide error label and remove error class on focus if enabled
          			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
          				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
          				this.errorsFor(element).hide();
          			}
          		},
          		onfocusout: function(element) {
          			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
          				this.element(element);
          			}
          		},
          		onkeyup: function(element) {
          			if ( element.name in this.submitted || element == this.lastElement ) {
          				this.element(element);
          			}
          		},
          		onclick: function(element) {
          			// click on selects, radiobuttons and checkboxes
          			if ( element.name in this.submitted )
          				this.element(element);
          			// or option elements, check parent select in that case
          			else if (element.parentNode.name in this.submitted)
          				this.element(element.parentNode);
          		},
          		highlight: function( element, errorClass, validClass ) {
          			$(element).addClass(errorClass).removeClass(validClass);
          		},
          		unhighlight: function( element, errorClass, validClass ) {
          			$(element).removeClass(errorClass).addClass(validClass);
          		}
          	},
          
          	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
          	setDefaults: function(settings) {
          		$.extend( $.validator.defaults, settings );
          	},
          
          	messages: {
          		required: "This field is required.",
          		remote: "Please fix this field.",
          		email: "Please enter a valid email address.",
          		url: "Please enter a valid URL.",
          		date: "Please enter a valid date.",
          		dateISO: "Please enter a valid date (ISO).",
          		number: "Please enter a valid number.",
          		digits: "Please enter only digits.",
          		creditcard: "Please enter a valid credit card number.",
          		equalTo: "Please enter the same value again.",
          		accept: "Please enter a value with a valid extension.",
          		maxlength: $.validator.format("Please enter no more than {0} characters."),
          		minlength: $.validator.format("Please enter at least {0} characters."),
          		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
          		range: $.validator.format("Please enter a value between {0} and {1}."),
          		max: $.validator.format("Please enter a value less than or equal to {0}."),
          		min: $.validator.format("Please enter a value greater than or equal to {0}.")
          	},
          	
          	autoCreateRanges: false,
          	
          	prototype: {
          		
          		init: function() {
          			this.labelContainer = $(this.settings.errorLabelContainer);
          			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
          			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
          			this.submitted = {};
          			this.valueCache = {};
          			this.pendingRequest = 0;
          			this.pending = {};
          			this.invalid = {};
          			this.reset();
          			
          			var groups = (this.groups = {});
          			$.each(this.settings.groups, function(key, value) {
          				$.each(value.split(/\s/), function(index, name) {
          					groups[name] = key;
          				});
          			});
          			var rules = this.settings.rules;
          			$.each(rules, function(key, value) {
          				rules[key] = $.validator.normalizeRule(value);
          			});
          			
          			function delegate(event) {
          				var validator = $.data(this[0].form, "validator"),
          					eventType = "on" + event.type.replace(/^validate/, "");
          				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
          			}
          			$(this.currentForm)
          				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
          				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);
          
          			if (this.settings.invalidHandler)
          				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/form
          		form: function() {
          			this.checkForm();
          			$.extend(this.submitted, this.errorMap);
          			this.invalid = $.extend({}, this.errorMap);
          			if (!this.valid())
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          			this.showErrors();
          			return this.valid();
          		},
          		
          		checkForm: function() {
          			this.prepareForm();
          			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
          				this.check( elements[i] );
          			}
          			return this.valid(); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/element
          		element: function( element ) {
          			element = this.clean( element );
          			this.lastElement = element;
          			this.prepareElement( element );
          			this.currentElements = $(element);
          			var result = this.check( element );
          			if ( result ) {
          				delete this.invalid[element.name];
          			} else {
          				this.invalid[element.name] = true;
          			}
          			if ( !this.numberOfInvalids() ) {
          				// Hide error containers on last error
          				this.toHide = this.toHide.add( this.containers );
          			}
          			this.showErrors();
          			return result;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
          		showErrors: function(errors) {
          			if(errors) {
          				// add items to error list and map
          				$.extend( this.errorMap, errors );
          				this.errorList = [];
          				for ( var name in errors ) {
          					this.errorList.push({
          						message: errors[name],
          						element: this.findByName(name)[0]
          					});
          				}
          				// remove items from success list
          				this.successList = $.grep( this.successList, function(element) {
          					return !(element.name in errors);
          				});
          			}
          			this.settings.showErrors
          				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
          				: this.defaultShowErrors();
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
          		resetForm: function() {
          			if ( $.fn.resetForm )
          				$( this.currentForm ).resetForm();
          			this.submitted = {};
          			this.prepareForm();
          			this.hideErrors();
          			this.elements().removeClass( this.settings.errorClass );
          		},
          		
          		numberOfInvalids: function() {
          			return this.objectLength(this.invalid);
          		},
          		
          		objectLength: function( obj ) {
          			var count = 0;
          			for ( var i in obj )
          				count++;
          			return count;
          		},
          		
          		hideErrors: function() {
          			this.addWrapper( this.toHide ).hide();
          		},
          		
          		valid: function() {
          			return this.size() == 0;
          		},
          		
          		size: function() {
          			return this.errorList.length;
          		},
          		
          		focusInvalid: function() {
          			if( this.settings.focusInvalid ) {
          				try {
          					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
          					.filter(":visible")
          					.focus()
          					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
          					.trigger("focusin");
          				} catch(e) {
          					// ignore IE throwing errors when focusing hidden elements
          				}
          			}
          		},
          		
          		findLastActive: function() {
          			var lastActive = this.lastActive;
          			return lastActive && $.grep(this.errorList, function(n) {
          				return n.element.name == lastActive.name;
          			}).length == 1 && lastActive;
          		},
          		
          		elements: function() {
          			var validator = this,
          				rulesCache = {};
          			
          			// select all valid inputs inside the form (no submit or reset buttons)
          			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
          			return $([]).add(this.currentForm.elements)
          			.filter(":input")
          			.not(":submit, :reset, :image, [disabled]")
          			.not( this.settings.ignore )
          			.filter(function() {
          				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
          			
          				// select only the first element for each name, and only those with rules specified
          				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
          					return false;
          				
          				rulesCache[this.name] = true;
          				return true;
          			});
          		},
          		
          		clean: function( selector ) {
          			return $( selector )[0];
          		},
          		
          		errors: function() {
          			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
          		},
          		
          		reset: function() {
          			this.successList = [];
          			this.errorList = [];
          			this.errorMap = {};
          			this.toShow = $([]);
          			this.toHide = $([]);
          			this.currentElements = $([]);
          		},
          		
          		prepareForm: function() {
          			this.reset();
          			this.toHide = this.errors().add( this.containers );
          		},
          		
          		prepareElement: function( element ) {
          			this.reset();
          			this.toHide = this.errorsFor(element);
          		},
          	
          		check: function( element ) {
          			element = this.clean( element );
          			
          			// if radio/checkbox, validate first element in group instead
          			if (this.checkable(element)) {
          				element = this.findByName( element.name )[0];
          			}
          			
          			var rules = $(element).rules();
          			var dependencyMismatch = false;
          			for( method in rules ) {
          				var rule = { method: method, parameters: rules[method] };
          				try {
          					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
          					
          					// if a method indicates that the field is optional and therefore valid,
          					// don't mark it as valid when there are no other rules
          					if ( result == "dependency-mismatch" ) {
          						dependencyMismatch = true;
          						continue;
          					}
          					dependencyMismatch = false;
          					
          					if ( result == "pending" ) {
          						this.toHide = this.toHide.not( this.errorsFor(element) );
          						return;
          					}
          					
          					if( !result ) {
          						this.formatAndAdd( element, rule );
          						return false;
          					}
          				} catch(e) {
          					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
          						 + ", check the '" + rule.method + "' method", e);
          					throw e;
          				}
          			}
          			if (dependencyMismatch)
          				return;
          			if ( this.objectLength(rules) )
          				this.successList.push(element);
          			return true;
          		},
          		
          		// return the custom message for the given element and validation method
          		// specified in the element's "messages" metadata
          		customMetaMessage: function(element, method) {
          			if (!$.metadata)
          				return;
          			
          			var meta = this.settings.meta
          				? $(element).metadata()[this.settings.meta]
          				: $(element).metadata();
          			
          			return meta && meta.messages && meta.messages[method];
          		},
          		
          		// return the custom message for the given element name and validation method
          		customMessage: function( name, method ) {
          			var m = this.settings.messages[name];
          			return m && (m.constructor == String
          				? m
          				: m[method]);
          		},
          		
          		// return the first defined argument, allowing empty strings
          		findDefined: function() {
          			for(var i = 0; i < arguments.length; i++) {
          				if (arguments[i] !== undefined)
          					return arguments[i];
          			}
          			return undefined;
          		},
          		
          		defaultMessage: function( element, method) {
          			return this.findDefined(
          				this.customMessage( element.name, method ),
          				this.customMetaMessage( element, method ),
          				// title is never undefined, so handle empty string as undefined
          				!this.settings.ignoreTitle && element.title || undefined,
          				$.validator.messages[method],
          				"<strong>Warning: No message defined for " + element.name + "</strong>"
          			);
          		},
          		
          		formatAndAdd: function( element, rule ) {
          			var message = this.defaultMessage( element, rule.method ),
          				theregex = /\$?\{(\d+)\}/g;
          			if ( typeof message == "function" ) {
          				message = message.call(this, rule.parameters, element);
          			} else if (theregex.test(message)) {
          				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
          			}			
          			this.errorList.push({
          				message: message,
          				element: element
          			});
          			
          			this.errorMap[element.name] = message;
          			this.submitted[element.name] = message;
          		},
          		
          		addWrapper: function(toToggle) {
          			if ( this.settings.wrapper )
          				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
          			return toToggle;
          		},
          		
          		defaultShowErrors: function() {
          			for ( var i = 0; this.errorList[i]; i++ ) {
          				var error = this.errorList[i];
          				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
          				this.showLabel( error.element, error.message );
          			}
          			if( this.errorList.length ) {
          				this.toShow = this.toShow.add( this.containers );
          			}
          			if (this.settings.success) {
          				for ( var i = 0; this.successList[i]; i++ ) {
          					this.showLabel( this.successList[i] );
          				}
          			}
          			if (this.settings.unhighlight) {
          				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
          					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
          				}
          			}
          			this.toHide = this.toHide.not( this.toShow );
          			this.hideErrors();
          			this.addWrapper( this.toShow ).show();
          		},
          		
          		validElements: function() {
          			return this.currentElements.not(this.invalidElements());
          		},
          		
          		invalidElements: function() {
          			return $(this.errorList).map(function() {
          				return this.element;
          			});
          		},
          		
          		showLabel: function(element, message) {
          			var label = this.errorsFor( element );
          			if ( label.length ) {
          				// refresh error/success class
          				label.removeClass().addClass( this.settings.errorClass );
          			
          				// check if we have a generated label, replace the message then
          				label.attr("generated") && label.html(message);
          			} else {
          				// create label
          				label = $("<" + this.settings.errorElement + "/>")
          					.attr({"for":  this.idOrName(element), generated: true})
          					.addClass(this.settings.errorClass)
          					.html(message || "");
          				if ( this.settings.wrapper ) {
          					// make sure the element is visible, even in IE
          					// actually showing the wrapped element is handled elsewhere
          					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
          				}
          				if ( !this.labelContainer.append(label).length )
          					this.settings.errorPlacement
          						? this.settings.errorPlacement(label, $(element) )
          						: label.insertAfter(element);
          			}
          			if ( !message && this.settings.success ) {
          				label.text("");
          				typeof this.settings.success == "string"
          					? label.addClass( this.settings.success )
          					: this.settings.success( label );
          			}
          			this.toShow = this.toShow.add(label);
          		},
          		
          		errorsFor: function(element) {
          			var name = this.idOrName(element);
              		return this.errors().filter(function() {
          				return $(this).attr('for') == name;
          			});
          		},
          		
          		idOrName: function(element) {
          			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
          		},
          
          		checkable: function( element ) {
          			return /radio|checkbox/i.test(element.type);
          		},
          		
          		findByName: function( name ) {
          			// select by name and filter by form for performance over form.find("[name=...]")
          			var form = this.currentForm;
          			return $(document.getElementsByName(name)).map(function(index, element) {
          				return element.form == form && element.name == name && element  || null;
          			});
          		},
          		
          		getLength: function(value, element) {
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				return $("option:selected", element).length;
          			case 'input':
          				if( this.checkable( element) )
          					return this.findByName(element.name).filter(':checked').length;
          			}
          			return value.length;
          		},
          	
          		depend: function(param, element) {
          			return this.dependTypes[typeof param]
          				? this.dependTypes[typeof param](param, element)
          				: true;
          		},
          	
          		dependTypes: {
          			"boolean": function(param, element) {
          				return param;
          			},
          			"string": function(param, element) {
          				return !!$(param, element.form).length;
          			},
          			"function": function(param, element) {
          				return param(element);
          			}
          		},
          		
          		optional: function(element) {
          			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
          		},
          		
          		startRequest: function(element) {
          			if (!this.pending[element.name]) {
          				this.pendingRequest++;
          				this.pending[element.name] = true;
          			}
          		},
          		
          		stopRequest: function(element, valid) {
          			this.pendingRequest--;
          			// sometimes synchronization fails, make sure pendingRequest is never < 0
          			if (this.pendingRequest < 0)
          				this.pendingRequest = 0;
          			delete this.pending[element.name];
          			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
          				$(this.currentForm).submit();
          				this.formSubmitted = false;
          			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          				this.formSubmitted = false;
          			}
          		},
          		
          		previousValue: function(element) {
          			return $.data(element, "previousValue") || $.data(element, "previousValue", {
          				old: null,
          				valid: true,
          				message: this.defaultMessage( element, "remote" )
          			});
          		}
          		
          	},
          	
          	classRuleSettings: {
          		required: {required: true},
          		email: {email: true},
          		url: {url: true},
          		date: {date: true},
          		dateISO: {dateISO: true},
          		dateDE: {dateDE: true},
          		number: {number: true},
          		numberDE: {numberDE: true},
          		digits: {digits: true},
          		creditcard: {creditcard: true}
          	},
          	
          	addClassRules: function(className, rules) {
          		className.constructor == String ?
          			this.classRuleSettings[className] = rules :
          			$.extend(this.classRuleSettings, className);
          	},
          	
          	classRules: function(element) {
          		var rules = {};
          		var classes = $(element).attr('class');
          		classes && $.each(classes.split(' '), function() {
          			if (this in $.validator.classRuleSettings) {
          				$.extend(rules, $.validator.classRuleSettings[this]);
          			}
          		});
          		return rules;
          	},
          	
          	attributeRules: function(element) {
          		var rules = {};
          		var $element = $(element);
          		
          		for (method in $.validator.methods) {
          			var value = $element.attr(method);
          			if (value) {
          				rules[method] = value;
          			}
          		}
          		
          		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
          		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
          			delete rules.maxlength;
          		}
          		
          		return rules;
          	},
          	
          	metadataRules: function(element) {
          		if (!$.metadata) return {};
          		
          		var meta = $.data(element.form, 'validator').settings.meta;
          		return meta ?
          			$(element).metadata()[meta] :
          			$(element).metadata();
          	},
          	
          	staticRules: function(element) {
          		var rules = {};
          		var validator = $.data(element.form, 'validator');
          		if (validator.settings.rules) {
          			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
          		}
          		return rules;
          	},
          	
          	normalizeRules: function(rules, element) {
          		// handle dependency check
          		$.each(rules, function(prop, val) {
          			// ignore rule when param is explicitly false, eg. required:false
          			if (val === false) {
          				delete rules[prop];
          				return;
          			}
          			if (val.param || val.depends) {
          				var keepRule = true;
          				switch (typeof val.depends) {
          					case "string":
          						keepRule = !!$(val.depends, element.form).length;
          						break;
          					case "function":
          						keepRule = val.depends.call(element, element);
          						break;
          				}
          				if (keepRule) {
          					rules[prop] = val.param !== undefined ? val.param : true;
          				} else {
          					delete rules[prop];
          				}
          			}
          		});
          		
          		// evaluate parameters
          		$.each(rules, function(rule, parameter) {
          			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
          		});
          		
          		// clean number parameters
          		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
          			if (rules[this]) {
          				rules[this] = Number(rules[this]);
          			}
          		});
          		$.each(['rangelength', 'range'], function() {
          			if (rules[this]) {
          				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
          			}
          		});
          		
          		if ($.validator.autoCreateRanges) {
          			// auto-create ranges
          			if (rules.min && rules.max) {
          				rules.range = [rules.min, rules.max];
          				delete rules.min;
          				delete rules.max;
          			}
          			if (rules.minlength && rules.maxlength) {
          				rules.rangelength = [rules.minlength, rules.maxlength];
          				delete rules.minlength;
          				delete rules.maxlength;
          			}
          		}
          		
          		// To support custom messages in metadata ignore rule methods titled "messages"
          		if (rules.messages) {
          			delete rules.messages;
          		}
          		
          		return rules;
          	},
          	
          	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
          	normalizeRule: function(data) {
          		if( typeof data == "string" ) {
          			var transformed = {};
          			$.each(data.split(/\s/), function() {
          				transformed[this] = true;
          			});
          			data = transformed;
          		}
          		return data;
          	},
          	
          	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
          	addMethod: function(name, method, message) {
          		$.validator.methods[name] = method;
          		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
          		if (method.length < 3) {
          			$.validator.addClassRules(name, $.validator.normalizeRule(name));
          		}
          	},
          
          	methods: {
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/required
          		required: function(value, element, param) {
          			// check if dependency is met
          			if ( !this.depend(param, element) )
          				return "dependency-mismatch";
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				// could be an array for select-multiple or a string, both are fine this way
          				var val = $(element).val();
          				return val && val.length > 0;
          			case 'input':
          				if ( this.checkable(element) )
          					return this.getLength(value, element) > 0;
          			default:
          				return $.trim(value).length > 0;
          			}
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/remote
          		remote: function(value, element, param) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			
          			var previous = this.previousValue(element);
          			if (!this.settings.messages[element.name] )
          				this.settings.messages[element.name] = {};
          			previous.originalMessage = this.settings.messages[element.name].remote;
          			this.settings.messages[element.name].remote = previous.message;
          			
          			param = typeof param == "string" && {url:param} || param; 
          			
          			if ( previous.old !== value ) {
          				previous.old = value;
          				var validator = this;
          				this.startRequest(element);
          				var data = {};
          				data[element.name] = value;
          				$.ajax($.extend(true, {
          					url: param,
          					mode: "abort",
          					port: "validate" + element.name,
          					dataType: "json",
          					data: data,
          					success: function(response) {
          						validator.settings.messages[element.name].remote = previous.originalMessage;
          						var valid = response === true;
          						if ( valid ) {
          							var submitted = validator.formSubmitted;
          							validator.prepareElement(element);
          							validator.formSubmitted = submitted;
          							validator.successList.push(element);
          							validator.showErrors();
          						} else {
          							var errors = {};
          							var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
          							errors[element.name] = $.isFunction(message) ? message(value) : message;
          							validator.showErrors(errors);
          						}
          						previous.valid = valid;
          						validator.stopRequest(element, valid);
          					}
          				}, param));
          				return "pending";
          			} else if( this.pending[element.name] ) {
          				return "pending";
          			}
          			return previous.valid;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
          		minlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
          		maxlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
          		rangelength: function(value, element, param) {
          			var length = this.getLength($.trim(value), element);
          			return this.optional(element) || ( length >= param[0] && length <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/min
          		min: function( value, element, param ) {
          			return this.optional(element) || value >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/max
          		max: function( value, element, param ) {
          			return this.optional(element) || value <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/range
          		range: function( value, element, param ) {
          			return this.optional(element) || ( value >= param[0] && value <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/email
          		email: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
          			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/url
          		url: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
          			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
          		},
                  
          		// http://docs.jquery.com/Plugins/Validation/Methods/date
          		date: function(value, element) {
          			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
          		dateISO: function(value, element) {
          			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/number
          		number: function(value, element) {
          			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/digits
          		digits: function(value, element) {
          			return this.optional(element) || /^\d+$/.test(value);
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
          		// based on http://en.wikipedia.org/wiki/Luhn
          		creditcard: function(value, element) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			// accept only digits and dashes
          			if (/[^0-9-]+/.test(value))
          				return false;
          			var nCheck = 0,
          				nDigit = 0,
          				bEven = false;
          
          			value = value.replace(/\D/g, "");
          
          			for (var n = value.length - 1; n >= 0; n--) {
          				var cDigit = value.charAt(n);
          				var nDigit = parseInt(cDigit, 10);
          				if (bEven) {
          					if ((nDigit *= 2) > 9)
          						nDigit -= 9;
          				}
          				nCheck += nDigit;
          				bEven = !bEven;
          			}
          
          			return (nCheck % 10) == 0;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/accept
          		accept: function(value, element, param) {
          			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
          			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
          		equalTo: function(value, element, param) {
          			// bind to the blur event of the target in order to revalidate whenever the target field is updated
          			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
          			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
          				$(element).valid();
          			});
          			return value == target.val();
          		}
          		
          	}
          	
          });
          
          // deprecated, use $.validator.format instead
          $.format = $.validator.format;
          
          })(jQuery);
          
          // ajax mode: abort
          // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
          // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
          ;(function($) {
          	var ajax = $.ajax;
          	var pendingRequests = {};
          	$.ajax = function(settings) {
          		// create settings for compatibility with ajaxSetup
          		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
          		var port = settings.port;
          		if (settings.mode == "abort") {
          			if ( pendingRequests[port] ) {
          				pendingRequests[port].abort();
          			}
          			return (pendingRequests[port] = ajax.apply(this, arguments));
          		}
          		return ajax.apply(this, arguments);
          	};
          })(jQuery);
          
          // provides cross-browser focusin and focusout events
          // IE has native support, in other browsers, use event caputuring (neither bubbles)
          
          // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
          // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
          ;(function($) {
          	// only implement if not provided by jQuery core (since 1.4)
          	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
          	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
          		$.each({
          			focus: 'focusin',
          			blur: 'focusout'	
          		}, function( original, fix ){
          			$.event.special[fix] = {
          				setup:function() {
          					this.addEventListener( original, handler, true );
          				},
          				teardown:function() {
          					this.removeEventListener( original, handler, true );
          				},
          				handler: function(e) {
          					arguments[0] = $.event.fix(e);
          					arguments[0].type = fix;
          					return $.event.handle.apply(this, arguments);
          				}
          			};
          			function handler(e) {
          				e = $.event.fix(e);
          				e.type = fix;
          				return $.event.handle.call(this, e);
          			}
          		});
          	};
          	$.extend($.fn, {
          		validateDelegate: function(delegate, type, handler) {
          			return this.bind(type, function(event) {
          				var target = $(event.target);
          				if (target.is(delegate)) {
          					return handler.apply(target, arguments);
          				}
          			});
          		}
          	});
          })(jQuery);
          
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        19. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bQUERY\b and was detected in the element starting with: " // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (397 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 37133
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"37133-1268175436000"
          Last-Modified: Tue, 09 Mar 2010 22:57:16 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (37133 bytes)
          /*
           * jQuery validation plug-in 1.7
           *
           * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
           * http://docs.jquery.com/Plugins/Validation
           *
           * Copyright (c) 2006 - 2008 Jörn Zaefferer
           *
           * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          $.extend($.fn, {
          	// http://docs.jquery.com/Plugins/Validation/validate
          	validate: function( options ) {
          
          		// if nothing is selected, return nothing; can't chain anyway
          		if (!this.length) {
          			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
          			return;
          		}
          
          		// check if a validator for this form was already created
          		var validator = $.data(this[0], 'validator');
          		if ( validator ) {
          			return validator;
          		}
          		
          		validator = new $.validator( options, this[0] );
          		$.data(this[0], 'validator', validator); 
          		
          		if ( validator.settings.onsubmit ) {
          		
          			// allow suppresing validation by adding a cancel class to the submit button
          			this.find("input, button").filter(".cancel").click(function() {
          				validator.cancelSubmit = true;
          			});
          			
          			// when a submitHandler is used, capture the submitting button
          			if (validator.settings.submitHandler) {
          				this.find("input, button").filter(":submit").click(function() {
          					validator.submitButton = this;
          				});
          			}
          		
          			// validate the form on submit
          			this.submit( function( event ) {
          				if ( validator.settings.debug )
          					// prevent form submit to be able to see console output
          					event.preventDefault();
          					
          				function handle() {
          					if ( validator.settings.submitHandler ) {
          						if (validator.submitButton) {
          							// insert a hidden input as a replacement for the missing submit button
          							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
          						}
          						validator.settings.submitHandler.call( validator, validator.currentForm );
          						if (validator.submitButton) {
          							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
          							hidden.remove();
          						}
          						return false;
          					}
          					return true;
          				}
          					
          				// prevent submit for invalid forms or custom submit handlers
          				if ( validator.cancelSubmit ) {
          					validator.cancelSubmit = false;
          					return handle();
          				}
          				if ( validator.form() ) {
          					if ( validator.pendingRequest ) {
          						validator.formSubmitted = true;
          						return false;
          					}
          					return handle();
          				} else {
          					validator.focusInvalid();
          					return false;
          				}
          			});
          		}
          		
          		return validator;
          	},
          	// http://docs.jquery.com/Plugins/Validation/valid
          	valid: function() {
                  if ( $(this[0]).is('form')) {
                      return this.validate().form();
                  } else {
                      var valid = true;
                      var validator = $(this[0].form).validate();
                      this.each(function() {
          				valid &= validator.element(this);
                      });
                      return valid;
                  }
              },
          	// attributes: space seperated list of attributes to retrieve and remove
          	removeAttrs: function(attributes) {
          		var result = {},
          			$element = this;
          		$.each(attributes.split(/\s/), function(index, value) {
          			result[value] = $element.attr(value);
          			$element.removeAttr(value);
          		});
          		return result;
          	},
          	// http://docs.jquery.com/Plugins/Validation/rules
          	rules: function(command, argument) {
          		var element = this[0];
          		
          		if (command) {
          			var settings = $.data(element.form, 'validator').settings;
          			var staticRules = settings.rules;
          			var existingRules = $.validator.staticRules(element);
          			switch(command) {
          			case "add":
          				$.extend(existingRules, $.validator.normalizeRule(argument));
          				staticRules[element.name] = existingRules;
          				if (argument.messages)
          					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
          				break;
          			case "remove":
          				if (!argument) {
          					delete staticRules[element.name];
          					return existingRules;
          				}
          				var filtered = {};
          				$.each(argument.split(/\s/), function(index, method) {
          					filtered[method] = existingRules[method];
          					delete existingRules[method];
          				});
          				return filtered;
          			}
          		}
          		
          		var data = $.validator.normalizeRules(
          		$.extend(
          			{},
          			$.validator.metadataRules(element),
          			$.validator.classRules(element),
          			$.validator.attributeRules(element),
          			$.validator.staticRules(element)
          		), element);
          		
          		// make sure required is at front
          		if (data.required) {
          			var param = data.required;
          			delete data.required;
          			data = $.extend({required: param}, data);
          		}
          		
          		return data;
          	}
          });
          
          // Custom selectors
          $.extend($.expr[":"], {
          	// http://docs.jquery.com/Plugins/Validation/blank
          	blank: function(a) {return !$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/filled
          	filled: function(a) {return !!$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/unchecked
          	unchecked: function(a) {return !a.checked;}
          });
          
          // constructor for validator
          $.validator = function( options, form ) {
          	this.settings = $.extend( true, {}, $.validator.defaults, options );
          	this.currentForm = form;
          	this.init();
          };
          
          $.validator.format = function(source, params) {
          	if ( arguments.length == 1 ) 
          		return function() {
          			var args = $.makeArray(arguments);
          			args.unshift(source);
          			return $.validator.format.apply( this, args );
          		};
          	if ( arguments.length > 2 && params.constructor != Array  ) {
          		params = $.makeArray(arguments).slice(1);
          	}
          	if ( params.constructor != Array ) {
          		params = [ params ];
          	}
          	$.each(params, function(i, n) {
          		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
          	});
          	return source;
          };
          
          $.extend($.validator, {
          	
          	defaults: {
          		messages: {},
          		groups: {},
          		rules: {},
          		errorClass: "error",
          		validClass: "valid",
          		errorElement: "label",
          		focusInvalid: true,
          		errorContainer: $( [] ),
          		errorLabelContainer: $( [] ),
          		onsubmit: true,
          		ignore: [],
          		ignoreTitle: false,
          		onfocusin: function(element) {
          			this.lastActive = element;
          				
          			// hide error label and remove error class on focus if enabled
          			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
          				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
          				this.errorsFor(element).hide();
          			}
          		},
          		onfocusout: function(element) {
          			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
          				this.element(element);
          			}
          		},
          		onkeyup: function(element) {
          			if ( element.name in this.submitted || element == this.lastElement ) {
          				this.element(element);
          			}
          		},
          		onclick: function(element) {
          			// click on selects, radiobuttons and checkboxes
          			if ( element.name in this.submitted )
          				this.element(element);
          			// or option elements, check parent select in that case
          			else if (element.parentNode.name in this.submitted)
          				this.element(element.parentNode);
          		},
          		highlight: function( element, errorClass, validClass ) {
          			$(element).addClass(errorClass).removeClass(validClass);
          		},
          		unhighlight: function( element, errorClass, validClass ) {
          			$(element).removeClass(errorClass).addClass(validClass);
          		}
          	},
          
          	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
          	setDefaults: function(settings) {
          		$.extend( $.validator.defaults, settings );
          	},
          
          	messages: {
          		required: "This field is required.",
          		remote: "Please fix this field.",
          		email: "Please enter a valid email address.",
          		url: "Please enter a valid URL.",
          		date: "Please enter a valid date.",
          		dateISO: "Please enter a valid date (ISO).",
          		number: "Please enter a valid number.",
          		digits: "Please enter only digits.",
          		creditcard: "Please enter a valid credit card number.",
          		equalTo: "Please enter the same value again.",
          		accept: "Please enter a value with a valid extension.",
          		maxlength: $.validator.format("Please enter no more than {0} characters."),
          		minlength: $.validator.format("Please enter at least {0} characters."),
          		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
          		range: $.validator.format("Please enter a value between {0} and {1}."),
          		max: $.validator.format("Please enter a value less than or equal to {0}."),
          		min: $.validator.format("Please enter a value greater than or equal to {0}.")
          	},
          	
          	autoCreateRanges: false,
          	
          	prototype: {
          		
          		init: function() {
          			this.labelContainer = $(this.settings.errorLabelContainer);
          			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
          			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
          			this.submitted = {};
          			this.valueCache = {};
          			this.pendingRequest = 0;
          			this.pending = {};
          			this.invalid = {};
          			this.reset();
          			
          			var groups = (this.groups = {});
          			$.each(this.settings.groups, function(key, value) {
          				$.each(value.split(/\s/), function(index, name) {
          					groups[name] = key;
          				});
          			});
          			var rules = this.settings.rules;
          			$.each(rules, function(key, value) {
          				rules[key] = $.validator.normalizeRule(value);
          			});
          			
          			function delegate(event) {
          				var validator = $.data(this[0].form, "validator"),
          					eventType = "on" + event.type.replace(/^validate/, "");
          				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
          			}
          			$(this.currentForm)
          				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
          				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);
          
          			if (this.settings.invalidHandler)
          				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/form
          		form: function() {
          			this.checkForm();
          			$.extend(this.submitted, this.errorMap);
          			this.invalid = $.extend({}, this.errorMap);
          			if (!this.valid())
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          			this.showErrors();
          			return this.valid();
          		},
          		
          		checkForm: function() {
          			this.prepareForm();
          			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
          				this.check( elements[i] );
          			}
          			return this.valid(); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/element
          		element: function( element ) {
          			element = this.clean( element );
          			this.lastElement = element;
          			this.prepareElement( element );
          			this.currentElements = $(element);
          			var result = this.check( element );
          			if ( result ) {
          				delete this.invalid[element.name];
          			} else {
          				this.invalid[element.name] = true;
          			}
          			if ( !this.numberOfInvalids() ) {
          				// Hide error containers on last error
          				this.toHide = this.toHide.add( this.containers );
          			}
          			this.showErrors();
          			return result;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
          		showErrors: function(errors) {
          			if(errors) {
          				// add items to error list and map
          				$.extend( this.errorMap, errors );
          				this.errorList = [];
          				for ( var name in errors ) {
          					this.errorList.push({
          						message: errors[name],
          						element: this.findByName(name)[0]
          					});
          				}
          				// remove items from success list
          				this.successList = $.grep( this.successList, function(element) {
          					return !(element.name in errors);
          				});
          			}
          			this.settings.showErrors
          				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
          				: this.defaultShowErrors();
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
          		resetForm: function() {
          			if ( $.fn.resetForm )
          				$( this.currentForm ).resetForm();
          			this.submitted = {};
          			this.prepareForm();
          			this.hideErrors();
          			this.elements().removeClass( this.settings.errorClass );
          		},
          		
          		numberOfInvalids: function() {
          			return this.objectLength(this.invalid);
          		},
          		
          		objectLength: function( obj ) {
          			var count = 0;
          			for ( var i in obj )
          				count++;
          			return count;
          		},
          		
          		hideErrors: function() {
          			this.addWrapper( this.toHide ).hide();
          		},
          		
          		valid: function() {
          			return this.size() == 0;
          		},
          		
          		size: function() {
          			return this.errorList.length;
          		},
          		
          		focusInvalid: function() {
          			if( this.settings.focusInvalid ) {
          				try {
          					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
          					.filter(":visible")
          					.focus()
          					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
          					.trigger("focusin");
          				} catch(e) {
          					// ignore IE throwing errors when focusing hidden elements
          				}
          			}
          		},
          		
          		findLastActive: function() {
          			var lastActive = this.lastActive;
          			return lastActive && $.grep(this.errorList, function(n) {
          				return n.element.name == lastActive.name;
          			}).length == 1 && lastActive;
          		},
          		
          		elements: function() {
          			var validator = this,
          				rulesCache = {};
          			
          			// select all valid inputs inside the form (no submit or reset buttons)
          			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
          			return $([]).add(this.currentForm.elements)
          			.filter(":input")
          			.not(":submit, :reset, :image, [disabled]")
          			.not( this.settings.ignore )
          			.filter(function() {
          				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
          			
          				// select only the first element for each name, and only those with rules specified
          				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
          					return false;
          				
          				rulesCache[this.name] = true;
          				return true;
          			});
          		},
          		
          		clean: function( selector ) {
          			return $( selector )[0];
          		},
          		
          		errors: function() {
          			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
          		},
          		
          		reset: function() {
          			this.successList = [];
          			this.errorList = [];
          			this.errorMap = {};
          			this.toShow = $([]);
          			this.toHide = $([]);
          			this.currentElements = $([]);
          		},
          		
          		prepareForm: function() {
          			this.reset();
          			this.toHide = this.errors().add( this.containers );
          		},
          		
          		prepareElement: function( element ) {
          			this.reset();
          			this.toHide = this.errorsFor(element);
          		},
          	
          		check: function( element ) {
          			element = this.clean( element );
          			
          			// if radio/checkbox, validate first element in group instead
          			if (this.checkable(element)) {
          				element = this.findByName( element.name )[0];
          			}
          			
          			var rules = $(element).rules();
          			var dependencyMismatch = false;
          			for( method in rules ) {
          				var rule = { method: method, parameters: rules[method] };
          				try {
          					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
          					
          					// if a method indicates that the field is optional and therefore valid,
          					// don't mark it as valid when there are no other rules
          					if ( result == "dependency-mismatch" ) {
          						dependencyMismatch = true;
          						continue;
          					}
          					dependencyMismatch = false;
          					
          					if ( result == "pending" ) {
          						this.toHide = this.toHide.not( this.errorsFor(element) );
          						return;
          					}
          					
          					if( !result ) {
          						this.formatAndAdd( element, rule );
          						return false;
          					}
          				} catch(e) {
          					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
          						 + ", check the '" + rule.method + "' method", e);
          					throw e;
          				}
          			}
          			if (dependencyMismatch)
          				return;
          			if ( this.objectLength(rules) )
          				this.successList.push(element);
          			return true;
          		},
          		
          		// return the custom message for the given element and validation method
          		// specified in the element's "messages" metadata
          		customMetaMessage: function(element, method) {
          			if (!$.metadata)
          				return;
          			
          			var meta = this.settings.meta
          				? $(element).metadata()[this.settings.meta]
          				: $(element).metadata();
          			
          			return meta && meta.messages && meta.messages[method];
          		},
          		
          		// return the custom message for the given element name and validation method
          		customMessage: function( name, method ) {
          			var m = this.settings.messages[name];
          			return m && (m.constructor == String
          				? m
          				: m[method]);
          		},
          		
          		// return the first defined argument, allowing empty strings
          		findDefined: function() {
          			for(var i = 0; i < arguments.length; i++) {
          				if (arguments[i] !== undefined)
          					return arguments[i];
          			}
          			return undefined;
          		},
          		
          		defaultMessage: function( element, method) {
          			return this.findDefined(
          				this.customMessage( element.name, method ),
          				this.customMetaMessage( element, method ),
          				// title is never undefined, so handle empty string as undefined
          				!this.settings.ignoreTitle && element.title || undefined,
          				$.validator.messages[method],
          				"<strong>Warning: No message defined for " + element.name + "</strong>"
          			);
          		},
          		
          		formatAndAdd: function( element, rule ) {
          			var message = this.defaultMessage( element, rule.method ),
          				theregex = /\$?\{(\d+)\}/g;
          			if ( typeof message == "function" ) {
          				message = message.call(this, rule.parameters, element);
          			} else if (theregex.test(message)) {
          				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
          			}			
          			this.errorList.push({
          				message: message,
          				element: element
          			});
          			
          			this.errorMap[element.name] = message;
          			this.submitted[element.name] = message;
          		},
          		
          		addWrapper: function(toToggle) {
          			if ( this.settings.wrapper )
          				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
          			return toToggle;
          		},
          		
          		defaultShowErrors: function() {
          			for ( var i = 0; this.errorList[i]; i++ ) {
          				var error = this.errorList[i];
          				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
          				this.showLabel( error.element, error.message );
          			}
          			if( this.errorList.length ) {
          				this.toShow = this.toShow.add( this.containers );
          			}
          			if (this.settings.success) {
          				for ( var i = 0; this.successList[i]; i++ ) {
          					this.showLabel( this.successList[i] );
          				}
          			}
          			if (this.settings.unhighlight) {
          				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
          					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
          				}
          			}
          			this.toHide = this.toHide.not( this.toShow );
          			this.hideErrors();
          			this.addWrapper( this.toShow ).show();
          		},
          		
          		validElements: function() {
          			return this.currentElements.not(this.invalidElements());
          		},
          		
          		invalidElements: function() {
          			return $(this.errorList).map(function() {
          				return this.element;
          			});
          		},
          		
          		showLabel: function(element, message) {
          			var label = this.errorsFor( element );
          			if ( label.length ) {
          				// refresh error/success class
          				label.removeClass().addClass( this.settings.errorClass );
          			
          				// check if we have a generated label, replace the message then
          				label.attr("generated") && label.html(message);
          			} else {
          				// create label
          				label = $("<" + this.settings.errorElement + "/>")
          					.attr({"for":  this.idOrName(element), generated: true})
          					.addClass(this.settings.errorClass)
          					.html(message || "");
          				if ( this.settings.wrapper ) {
          					// make sure the element is visible, even in IE
          					// actually showing the wrapped element is handled elsewhere
          					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
          				}
          				if ( !this.labelContainer.append(label).length )
          					this.settings.errorPlacement
          						? this.settings.errorPlacement(label, $(element) )
          						: label.insertAfter(element);
          			}
          			if ( !message && this.settings.success ) {
          				label.text("");
          				typeof this.settings.success == "string"
          					? label.addClass( this.settings.success )
          					: this.settings.success( label );
          			}
          			this.toShow = this.toShow.add(label);
          		},
          		
          		errorsFor: function(element) {
          			var name = this.idOrName(element);
              		return this.errors().filter(function() {
          				return $(this).attr('for') == name;
          			});
          		},
          		
          		idOrName: function(element) {
          			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
          		},
          
          		checkable: function( element ) {
          			return /radio|checkbox/i.test(element.type);
          		},
          		
          		findByName: function( name ) {
          			// select by name and filter by form for performance over form.find("[name=...]")
          			var form = this.currentForm;
          			return $(document.getElementsByName(name)).map(function(index, element) {
          				return element.form == form && element.name == name && element  || null;
          			});
          		},
          		
          		getLength: function(value, element) {
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				return $("option:selected", element).length;
          			case 'input':
          				if( this.checkable( element) )
          					return this.findByName(element.name).filter(':checked').length;
          			}
          			return value.length;
          		},
          	
          		depend: function(param, element) {
          			return this.dependTypes[typeof param]
          				? this.dependTypes[typeof param](param, element)
          				: true;
          		},
          	
          		dependTypes: {
          			"boolean": function(param, element) {
          				return param;
          			},
          			"string": function(param, element) {
          				return !!$(param, element.form).length;
          			},
          			"function": function(param, element) {
          				return param(element);
          			}
          		},
          		
          		optional: function(element) {
          			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
          		},
          		
          		startRequest: function(element) {
          			if (!this.pending[element.name]) {
          				this.pendingRequest++;
          				this.pending[element.name] = true;
          			}
          		},
          		
          		stopRequest: function(element, valid) {
          			this.pendingRequest--;
          			// sometimes synchronization fails, make sure pendingRequest is never < 0
          			if (this.pendingRequest < 0)
          				this.pendingRequest = 0;
          			delete this.pending[element.name];
          			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
          				$(this.currentForm).submit();
          				this.formSubmitted = false;
          			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          				this.formSubmitted = false;
          			}
          		},
          		
          		previousValue: function(element) {
          			return $.data(element, "previousValue") || $.data(element, "previousValue", {
          				old: null,
          				valid: true,
          				message: this.defaultMessage( element, "remote" )
          			});
          		}
          		
          	},
          	
          	classRuleSettings: {
          		required: {required: true},
          		email: {email: true},
          		url: {url: true},
          		date: {date: true},
          		dateISO: {dateISO: true},
          		dateDE: {dateDE: true},
          		number: {number: true},
          		numberDE: {numberDE: true},
          		digits: {digits: true},
          		creditcard: {creditcard: true}
          	},
          	
          	addClassRules: function(className, rules) {
          		className.constructor == String ?
          			this.classRuleSettings[className] = rules :
          			$.extend(this.classRuleSettings, className);
          	},
          	
          	classRules: function(element) {
          		var rules = {};
          		var classes = $(element).attr('class');
          		classes && $.each(classes.split(' '), function() {
          			if (this in $.validator.classRuleSettings) {
          				$.extend(rules, $.validator.classRuleSettings[this]);
          			}
          		});
          		return rules;
          	},
          	
          	attributeRules: function(element) {
          		var rules = {};
          		var $element = $(element);
          		
          		for (method in $.validator.methods) {
          			var value = $element.attr(method);
          			if (value) {
          				rules[method] = value;
          			}
          		}
          		
          		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
          		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
          			delete rules.maxlength;
          		}
          		
          		return rules;
          	},
          	
          	metadataRules: function(element) {
          		if (!$.metadata) return {};
          		
          		var meta = $.data(element.form, 'validator').settings.meta;
          		return meta ?
          			$(element).metadata()[meta] :
          			$(element).metadata();
          	},
          	
          	staticRules: function(element) {
          		var rules = {};
          		var validator = $.data(element.form, 'validator');
          		if (validator.settings.rules) {
          			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
          		}
          		return rules;
          	},
          	
          	normalizeRules: function(rules, element) {
          		// handle dependency check
          		$.each(rules, function(prop, val) {
          			// ignore rule when param is explicitly false, eg. required:false
          			if (val === false) {
          				delete rules[prop];
          				return;
          			}
          			if (val.param || val.depends) {
          				var keepRule = true;
          				switch (typeof val.depends) {
          					case "string":
          						keepRule = !!$(val.depends, element.form).length;
          						break;
          					case "function":
          						keepRule = val.depends.call(element, element);
          						break;
          				}
          				if (keepRule) {
          					rules[prop] = val.param !== undefined ? val.param : true;
          				} else {
          					delete rules[prop];
          				}
          			}
          		});
          		
          		// evaluate parameters
          		$.each(rules, function(rule, parameter) {
          			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
          		});
          		
          		// clean number parameters
          		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
          			if (rules[this]) {
          				rules[this] = Number(rules[this]);
          			}
          		});
          		$.each(['rangelength', 'range'], function() {
          			if (rules[this]) {
          				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
          			}
          		});
          		
          		if ($.validator.autoCreateRanges) {
          			// auto-create ranges
          			if (rules.min && rules.max) {
          				rules.range = [rules.min, rules.max];
          				delete rules.min;
          				delete rules.max;
          			}
          			if (rules.minlength && rules.maxlength) {
          				rules.rangelength = [rules.minlength, rules.maxlength];
          				delete rules.minlength;
          				delete rules.maxlength;
          			}
          		}
          		
          		// To support custom messages in metadata ignore rule methods titled "messages"
          		if (rules.messages) {
          			delete rules.messages;
          		}
          		
          		return rules;
          	},
          	
          	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
          	normalizeRule: function(data) {
          		if( typeof data == "string" ) {
          			var transformed = {};
          			$.each(data.split(/\s/), function() {
          				transformed[this] = true;
          			});
          			data = transformed;
          		}
          		return data;
          	},
          	
          	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
          	addMethod: function(name, method, message) {
          		$.validator.methods[name] = method;
          		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
          		if (method.length < 3) {
          			$.validator.addClassRules(name, $.validator.normalizeRule(name));
          		}
          	},
          
          	methods: {
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/required
          		required: function(value, element, param) {
          			// check if dependency is met
          			if ( !this.depend(param, element) )
          				return "dependency-mismatch";
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				// could be an array for select-multiple or a string, both are fine this way
          				var val = $(element).val();
          				return val && val.length > 0;
          			case 'input':
          				if ( this.checkable(element) )
          					return this.getLength(value, element) > 0;
          			default:
          				return $.trim(value).length > 0;
          			}
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/remote
          		remote: function(value, element, param) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			
          			var previous = this.previousValue(element);
          			if (!this.settings.messages[element.name] )
          				this.settings.messages[element.name] = {};
          			previous.originalMessage = this.settings.messages[element.name].remote;
          			this.settings.messages[element.name].remote = previous.message;
          			
          			param = typeof param == "string" && {url:param} || param; 
          			
          			if ( previous.old !== value ) {
          				previous.old = value;
          				var validator = this;
          				this.startRequest(element);
          				var data = {};
          				data[element.name] = value;
          				$.ajax($.extend(true, {
          					url: param,
          					mode: "abort",
          					port: "validate" + element.name,
          					dataType: "json",
          					data: data,
          					success: function(response) {
          						validator.settings.messages[element.name].remote = previous.originalMessage;
          						var valid = response === true;
          						if ( valid ) {
          							var submitted = validator.formSubmitted;
          							validator.prepareElement(element);
          							validator.formSubmitted = submitted;
          							validator.successList.push(element);
          							validator.showErrors();
          						} else {
          							var errors = {};
          							var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
          							errors[element.name] = $.isFunction(message) ? message(value) : message;
          							validator.showErrors(errors);
          						}
          						previous.valid = valid;
          						validator.stopRequest(element, valid);
          					}
          				}, param));
          				return "pending";
          			} else if( this.pending[element.name] ) {
          				return "pending";
          			}
          			return previous.valid;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
          		minlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
          		maxlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
          		rangelength: function(value, element, param) {
          			var length = this.getLength($.trim(value), element);
          			return this.optional(element) || ( length >= param[0] && length <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/min
          		min: function( value, element, param ) {
          			return this.optional(element) || value >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/max
          		max: function( value, element, param ) {
          			return this.optional(element) || value <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/range
          		range: function( value, element, param ) {
          			return this.optional(element) || ( value >= param[0] && value <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/email
          		email: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
          			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/url
          		url: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
          			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
          		},
                  
          		// http://docs.jquery.com/Plugins/Validation/Methods/date
          		date: function(value, element) {
          			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
          		dateISO: function(value, element) {
          			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/number
          		number: function(value, element) {
          			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/digits
          		digits: function(value, element) {
          			return this.optional(element) || /^\d+$/.test(value);
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
          		// based on http://en.wikipedia.org/wiki/Luhn
          		creditcard: function(value, element) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			// accept only digits and dashes
          			if (/[^0-9-]+/.test(value))
          				return false;
          			var nCheck = 0,
          				nDigit = 0,
          				bEven = false;
          
          			value = value.replace(/\D/g, "");
          
          			for (var n = value.length - 1; n >= 0; n--) {
          				var cDigit = value.charAt(n);
          				var nDigit = parseInt(cDigit, 10);
          				if (bEven) {
          					if ((nDigit *= 2) > 9)
          						nDigit -= 9;
          				}
          				nCheck += nDigit;
          				bEven = !bEven;
          			}
          
          			return (nCheck % 10) == 0;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/accept
          		accept: function(value, element, param) {
          			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
          			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
          		equalTo: function(value, element, param) {
          			// bind to the blur event of the target in order to revalidate whenever the target field is updated
          			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
          			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
          				$(element).valid();
          			});
          			return value == target.val();
          		}
          		
          	}
          	
          });
          
          // deprecated, use $.validator.format instead
          $.format = $.validator.format;
          
          })(jQuery);
          
          // ajax mode: abort
          // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
          // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
          ;(function($) {
          	var ajax = $.ajax;
          	var pendingRequests = {};
          	$.ajax = function(settings) {
          		// create settings for compatibility with ajaxSetup
          		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
          		var port = settings.port;
          		if (settings.mode == "abort") {
          			if ( pendingRequests[port] ) {
          				pendingRequests[port].abort();
          			}
          			return (pendingRequests[port] = ajax.apply(this, arguments));
          		}
          		return ajax.apply(this, arguments);
          	};
          })(jQuery);
          
          // provides cross-browser focusin and focusout events
          // IE has native support, in other browsers, use event caputuring (neither bubbles)
          
          // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
          // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
          ;(function($) {
          	// only implement if not provided by jQuery core (since 1.4)
          	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
          	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
          		$.each({
          			focus: 'focusin',
          			blur: 'focusout'	
          		}, function( original, fix ){
          			$.event.special[fix] = {
          				setup:function() {
          					this.addEventListener( original, handler, true );
          				},
          				teardown:function() {
          					this.removeEventListener( original, handler, true );
          				},
          				handler: function(e) {
          					arguments[0] = $.event.fix(e);
          					arguments[0].type = fix;
          					return $.event.handle.apply(this, arguments);
          				}
          			};
          			function handler(e) {
          				e = $.event.fix(e);
          				e.type = fix;
          				return $.event.handle.call(this, e);
          			}
          		});
          	};
          	$.extend($.fn, {
          		validateDelegate: function(delegate, type, handler) {
          			return this.bind(type, function(event) {
          				var target = $(event.target);
          				if (target.is(delegate)) {
          					return handler.apply(target, arguments);
          				}
          			});
          		}
          	});
          })(jQuery);
          
          Evidence
          Query
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        20. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bSELECT\b and was detected 9 times, the first in the element starting with: " // or option elements, check parent select in that case", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (397 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 37133
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"37133-1268175436000"
          Last-Modified: Tue, 09 Mar 2010 22:57:16 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (37133 bytes)
          /*
           * jQuery validation plug-in 1.7
           *
           * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
           * http://docs.jquery.com/Plugins/Validation
           *
           * Copyright (c) 2006 - 2008 Jörn Zaefferer
           *
           * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          $.extend($.fn, {
          	// http://docs.jquery.com/Plugins/Validation/validate
          	validate: function( options ) {
          
          		// if nothing is selected, return nothing; can't chain anyway
          		if (!this.length) {
          			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
          			return;
          		}
          
          		// check if a validator for this form was already created
          		var validator = $.data(this[0], 'validator');
          		if ( validator ) {
          			return validator;
          		}
          		
          		validator = new $.validator( options, this[0] );
          		$.data(this[0], 'validator', validator); 
          		
          		if ( validator.settings.onsubmit ) {
          		
          			// allow suppresing validation by adding a cancel class to the submit button
          			this.find("input, button").filter(".cancel").click(function() {
          				validator.cancelSubmit = true;
          			});
          			
          			// when a submitHandler is used, capture the submitting button
          			if (validator.settings.submitHandler) {
          				this.find("input, button").filter(":submit").click(function() {
          					validator.submitButton = this;
          				});
          			}
          		
          			// validate the form on submit
          			this.submit( function( event ) {
          				if ( validator.settings.debug )
          					// prevent form submit to be able to see console output
          					event.preventDefault();
          					
          				function handle() {
          					if ( validator.settings.submitHandler ) {
          						if (validator.submitButton) {
          							// insert a hidden input as a replacement for the missing submit button
          							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
          						}
          						validator.settings.submitHandler.call( validator, validator.currentForm );
          						if (validator.submitButton) {
          							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
          							hidden.remove();
          						}
          						return false;
          					}
          					return true;
          				}
          					
          				// prevent submit for invalid forms or custom submit handlers
          				if ( validator.cancelSubmit ) {
          					validator.cancelSubmit = false;
          					return handle();
          				}
          				if ( validator.form() ) {
          					if ( validator.pendingRequest ) {
          						validator.formSubmitted = true;
          						return false;
          					}
          					return handle();
          				} else {
          					validator.focusInvalid();
          					return false;
          				}
          			});
          		}
          		
          		return validator;
          	},
          	// http://docs.jquery.com/Plugins/Validation/valid
          	valid: function() {
                  if ( $(this[0]).is('form')) {
                      return this.validate().form();
                  } else {
                      var valid = true;
                      var validator = $(this[0].form).validate();
                      this.each(function() {
          				valid &= validator.element(this);
                      });
                      return valid;
                  }
              },
          	// attributes: space seperated list of attributes to retrieve and remove
          	removeAttrs: function(attributes) {
          		var result = {},
          			$element = this;
          		$.each(attributes.split(/\s/), function(index, value) {
          			result[value] = $element.attr(value);
          			$element.removeAttr(value);
          		});
          		return result;
          	},
          	// http://docs.jquery.com/Plugins/Validation/rules
          	rules: function(command, argument) {
          		var element = this[0];
          		
          		if (command) {
          			var settings = $.data(element.form, 'validator').settings;
          			var staticRules = settings.rules;
          			var existingRules = $.validator.staticRules(element);
          			switch(command) {
          			case "add":
          				$.extend(existingRules, $.validator.normalizeRule(argument));
          				staticRules[element.name] = existingRules;
          				if (argument.messages)
          					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
          				break;
          			case "remove":
          				if (!argument) {
          					delete staticRules[element.name];
          					return existingRules;
          				}
          				var filtered = {};
          				$.each(argument.split(/\s/), function(index, method) {
          					filtered[method] = existingRules[method];
          					delete existingRules[method];
          				});
          				return filtered;
          			}
          		}
          		
          		var data = $.validator.normalizeRules(
          		$.extend(
          			{},
          			$.validator.metadataRules(element),
          			$.validator.classRules(element),
          			$.validator.attributeRules(element),
          			$.validator.staticRules(element)
          		), element);
          		
          		// make sure required is at front
          		if (data.required) {
          			var param = data.required;
          			delete data.required;
          			data = $.extend({required: param}, data);
          		}
          		
          		return data;
          	}
          });
          
          // Custom selectors
          $.extend($.expr[":"], {
          	// http://docs.jquery.com/Plugins/Validation/blank
          	blank: function(a) {return !$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/filled
          	filled: function(a) {return !!$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/unchecked
          	unchecked: function(a) {return !a.checked;}
          });
          
          // constructor for validator
          $.validator = function( options, form ) {
          	this.settings = $.extend( true, {}, $.validator.defaults, options );
          	this.currentForm = form;
          	this.init();
          };
          
          $.validator.format = function(source, params) {
          	if ( arguments.length == 1 ) 
          		return function() {
          			var args = $.makeArray(arguments);
          			args.unshift(source);
          			return $.validator.format.apply( this, args );
          		};
          	if ( arguments.length > 2 && params.constructor != Array  ) {
          		params = $.makeArray(arguments).slice(1);
          	}
          	if ( params.constructor != Array ) {
          		params = [ params ];
          	}
          	$.each(params, function(i, n) {
          		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
          	});
          	return source;
          };
          
          $.extend($.validator, {
          	
          	defaults: {
          		messages: {},
          		groups: {},
          		rules: {},
          		errorClass: "error",
          		validClass: "valid",
          		errorElement: "label",
          		focusInvalid: true,
          		errorContainer: $( [] ),
          		errorLabelContainer: $( [] ),
          		onsubmit: true,
          		ignore: [],
          		ignoreTitle: false,
          		onfocusin: function(element) {
          			this.lastActive = element;
          				
          			// hide error label and remove error class on focus if enabled
          			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
          				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
          				this.errorsFor(element).hide();
          			}
          		},
          		onfocusout: function(element) {
          			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
          				this.element(element);
          			}
          		},
          		onkeyup: function(element) {
          			if ( element.name in this.submitted || element == this.lastElement ) {
          				this.element(element);
          			}
          		},
          		onclick: function(element) {
          			// click on selects, radiobuttons and checkboxes
          			if ( element.name in this.submitted )
          				this.element(element);
          			// or option elements, check parent select in that case
          			else if (element.parentNode.name in this.submitted)
          				this.element(element.parentNode);
          		},
          		highlight: function( element, errorClass, validClass ) {
          			$(element).addClass(errorClass).removeClass(validClass);
          		},
          		unhighlight: function( element, errorClass, validClass ) {
          			$(element).removeClass(errorClass).addClass(validClass);
          		}
          	},
          
          	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
          	setDefaults: function(settings) {
          		$.extend( $.validator.defaults, settings );
          	},
          
          	messages: {
          		required: "This field is required.",
          		remote: "Please fix this field.",
          		email: "Please enter a valid email address.",
          		url: "Please enter a valid URL.",
          		date: "Please enter a valid date.",
          		dateISO: "Please enter a valid date (ISO).",
          		number: "Please enter a valid number.",
          		digits: "Please enter only digits.",
          		creditcard: "Please enter a valid credit card number.",
          		equalTo: "Please enter the same value again.",
          		accept: "Please enter a value with a valid extension.",
          		maxlength: $.validator.format("Please enter no more than {0} characters."),
          		minlength: $.validator.format("Please enter at least {0} characters."),
          		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
          		range: $.validator.format("Please enter a value between {0} and {1}."),
          		max: $.validator.format("Please enter a value less than or equal to {0}."),
          		min: $.validator.format("Please enter a value greater than or equal to {0}.")
          	},
          	
          	autoCreateRanges: false,
          	
          	prototype: {
          		
          		init: function() {
          			this.labelContainer = $(this.settings.errorLabelContainer);
          			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
          			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
          			this.submitted = {};
          			this.valueCache = {};
          			this.pendingRequest = 0;
          			this.pending = {};
          			this.invalid = {};
          			this.reset();
          			
          			var groups = (this.groups = {});
          			$.each(this.settings.groups, function(key, value) {
          				$.each(value.split(/\s/), function(index, name) {
          					groups[name] = key;
          				});
          			});
          			var rules = this.settings.rules;
          			$.each(rules, function(key, value) {
          				rules[key] = $.validator.normalizeRule(value);
          			});
          			
          			function delegate(event) {
          				var validator = $.data(this[0].form, "validator"),
          					eventType = "on" + event.type.replace(/^validate/, "");
          				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
          			}
          			$(this.currentForm)
          				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
          				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);
          
          			if (this.settings.invalidHandler)
          				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/form
          		form: function() {
          			this.checkForm();
          			$.extend(this.submitted, this.errorMap);
          			this.invalid = $.extend({}, this.errorMap);
          			if (!this.valid())
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          			this.showErrors();
          			return this.valid();
          		},
          		
          		checkForm: function() {
          			this.prepareForm();
          			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
          				this.check( elements[i] );
          			}
          			return this.valid(); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/element
          		element: function( element ) {
          			element = this.clean( element );
          			this.lastElement = element;
          			this.prepareElement( element );
          			this.currentElements = $(element);
          			var result = this.check( element );
          			if ( result ) {
          				delete this.invalid[element.name];
          			} else {
          				this.invalid[element.name] = true;
          			}
          			if ( !this.numberOfInvalids() ) {
          				// Hide error containers on last error
          				this.toHide = this.toHide.add( this.containers );
          			}
          			this.showErrors();
          			return result;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
          		showErrors: function(errors) {
          			if(errors) {
          				// add items to error list and map
          				$.extend( this.errorMap, errors );
          				this.errorList = [];
          				for ( var name in errors ) {
          					this.errorList.push({
          						message: errors[name],
          						element: this.findByName(name)[0]
          					});
          				}
          				// remove items from success list
          				this.successList = $.grep( this.successList, function(element) {
          					return !(element.name in errors);
          				});
          			}
          			this.settings.showErrors
          				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
          				: this.defaultShowErrors();
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
          		resetForm: function() {
          			if ( $.fn.resetForm )
          				$( this.currentForm ).resetForm();
          			this.submitted = {};
          			this.prepareForm();
          			this.hideErrors();
          			this.elements().removeClass( this.settings.errorClass );
          		},
          		
          		numberOfInvalids: function() {
          			return this.objectLength(this.invalid);
          		},
          		
          		objectLength: function( obj ) {
          			var count = 0;
          			for ( var i in obj )
          				count++;
          			return count;
          		},
          		
          		hideErrors: function() {
          			this.addWrapper( this.toHide ).hide();
          		},
          		
          		valid: function() {
          			return this.size() == 0;
          		},
          		
          		size: function() {
          			return this.errorList.length;
          		},
          		
          		focusInvalid: function() {
          			if( this.settings.focusInvalid ) {
          				try {
          					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
          					.filter(":visible")
          					.focus()
          					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
          					.trigger("focusin");
          				} catch(e) {
          					// ignore IE throwing errors when focusing hidden elements
          				}
          			}
          		},
          		
          		findLastActive: function() {
          			var lastActive = this.lastActive;
          			return lastActive && $.grep(this.errorList, function(n) {
          				return n.element.name == lastActive.name;
          			}).length == 1 && lastActive;
          		},
          		
          		elements: function() {
          			var validator = this,
          				rulesCache = {};
          			
          			// select all valid inputs inside the form (no submit or reset buttons)
          			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
          			return $([]).add(this.currentForm.elements)
          			.filter(":input")
          			.not(":submit, :reset, :image, [disabled]")
          			.not( this.settings.ignore )
          			.filter(function() {
          				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
          			
          				// select only the first element for each name, and only those with rules specified
          				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
          					return false;
          				
          				rulesCache[this.name] = true;
          				return true;
          			});
          		},
          		
          		clean: function( selector ) {
          			return $( selector )[0];
          		},
          		
          		errors: function() {
          			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
          		},
          		
          		reset: function() {
          			this.successList = [];
          			this.errorList = [];
          			this.errorMap = {};
          			this.toShow = $([]);
          			this.toHide = $([]);
          			this.currentElements = $([]);
          		},
          		
          		prepareForm: function() {
          			this.reset();
          			this.toHide = this.errors().add( this.containers );
          		},
          		
          		prepareElement: function( element ) {
          			this.reset();
          			this.toHide = this.errorsFor(element);
          		},
          	
          		check: function( element ) {
          			element = this.clean( element );
          			
          			// if radio/checkbox, validate first element in group instead
          			if (this.checkable(element)) {
          				element = this.findByName( element.name )[0];
          			}
          			
          			var rules = $(element).rules();
          			var dependencyMismatch = false;
          			for( method in rules ) {
          				var rule = { method: method, parameters: rules[method] };
          				try {
          					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
          					
          					// if a method indicates that the field is optional and therefore valid,
          					// don't mark it as valid when there are no other rules
          					if ( result == "dependency-mismatch" ) {
          						dependencyMismatch = true;
          						continue;
          					}
          					dependencyMismatch = false;
          					
          					if ( result == "pending" ) {
          						this.toHide = this.toHide.not( this.errorsFor(element) );
          						return;
          					}
          					
          					if( !result ) {
          						this.formatAndAdd( element, rule );
          						return false;
          					}
          				} catch(e) {
          					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
          						 + ", check the '" + rule.method + "' method", e);
          					throw e;
          				}
          			}
          			if (dependencyMismatch)
          				return;
          			if ( this.objectLength(rules) )
          				this.successList.push(element);
          			return true;
          		},
          		
          		// return the custom message for the given element and validation method
          		// specified in the element's "messages" metadata
          		customMetaMessage: function(element, method) {
          			if (!$.metadata)
          				return;
          			
          			var meta = this.settings.meta
          				? $(element).metadata()[this.settings.meta]
          				: $(element).metadata();
          			
          			return meta && meta.messages && meta.messages[method];
          		},
          		
          		// return the custom message for the given element name and validation method
          		customMessage: function( name, method ) {
          			var m = this.settings.messages[name];
          			return m && (m.constructor == String
          				? m
          				: m[method]);
          		},
          		
          		// return the first defined argument, allowing empty strings
          		findDefined: function() {
          			for(var i = 0; i < arguments.length; i++) {
          				if (arguments[i] !== undefined)
          					return arguments[i];
          			}
          			return undefined;
          		},
          		
          		defaultMessage: function( element, method) {
          			return this.findDefined(
          				this.customMessage( element.name, method ),
          				this.customMetaMessage( element, method ),
          				// title is never undefined, so handle empty string as undefined
          				!this.settings.ignoreTitle && element.title || undefined,
          				$.validator.messages[method],
          				"<strong>Warning: No message defined for " + element.name + "</strong>"
          			);
          		},
          		
          		formatAndAdd: function( element, rule ) {
          			var message = this.defaultMessage( element, rule.method ),
          				theregex = /\$?\{(\d+)\}/g;
          			if ( typeof message == "function" ) {
          				message = message.call(this, rule.parameters, element);
          			} else if (theregex.test(message)) {
          				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
          			}			
          			this.errorList.push({
          				message: message,
          				element: element
          			});
          			
          			this.errorMap[element.name] = message;
          			this.submitted[element.name] = message;
          		},
          		
          		addWrapper: function(toToggle) {
          			if ( this.settings.wrapper )
          				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
          			return toToggle;
          		},
          		
          		defaultShowErrors: function() {
          			for ( var i = 0; this.errorList[i]; i++ ) {
          				var error = this.errorList[i];
          				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
          				this.showLabel( error.element, error.message );
          			}
          			if( this.errorList.length ) {
          				this.toShow = this.toShow.add( this.containers );
          			}
          			if (this.settings.success) {
          				for ( var i = 0; this.successList[i]; i++ ) {
          					this.showLabel( this.successList[i] );
          				}
          			}
          			if (this.settings.unhighlight) {
          				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
          					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
          				}
          			}
          			this.toHide = this.toHide.not( this.toShow );
          			this.hideErrors();
          			this.addWrapper( this.toShow ).show();
          		},
          		
          		validElements: function() {
          			return this.currentElements.not(this.invalidElements());
          		},
          		
          		invalidElements: function() {
          			return $(this.errorList).map(function() {
          				return this.element;
          			});
          		},
          		
          		showLabel: function(element, message) {
          			var label = this.errorsFor( element );
          			if ( label.length ) {
          				// refresh error/success class
          				label.removeClass().addClass( this.settings.errorClass );
          			
          				// check if we have a generated label, replace the message then
          				label.attr("generated") && label.html(message);
          			} else {
          				// create label
          				label = $("<" + this.settings.errorElement + "/>")
          					.attr({"for":  this.idOrName(element), generated: true})
          					.addClass(this.settings.errorClass)
          					.html(message || "");
          				if ( this.settings.wrapper ) {
          					// make sure the element is visible, even in IE
          					// actually showing the wrapped element is handled elsewhere
          					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
          				}
          				if ( !this.labelContainer.append(label).length )
          					this.settings.errorPlacement
          						? this.settings.errorPlacement(label, $(element) )
          						: label.insertAfter(element);
          			}
          			if ( !message && this.settings.success ) {
          				label.text("");
          				typeof this.settings.success == "string"
          					? label.addClass( this.settings.success )
          					: this.settings.success( label );
          			}
          			this.toShow = this.toShow.add(label);
          		},
          		
          		errorsFor: function(element) {
          			var name = this.idOrName(element);
              		return this.errors().filter(function() {
          				return $(this).attr('for') == name;
          			});
          		},
          		
          		idOrName: function(element) {
          			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
          		},
          
          		checkable: function( element ) {
          			return /radio|checkbox/i.test(element.type);
          		},
          		
          		findByName: function( name ) {
          			// select by name and filter by form for performance over form.find("[name=...]")
          			var form = this.currentForm;
          			return $(document.getElementsByName(name)).map(function(index, element) {
          				return element.form == form && element.name == name && element  || null;
          			});
          		},
          		
          		getLength: function(value, element) {
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				return $("option:selected", element).length;
          			case 'input':
          				if( this.checkable( element) )
          					return this.findByName(element.name).filter(':checked').length;
          			}
          			return value.length;
          		},
          	
          		depend: function(param, element) {
          			return this.dependTypes[typeof param]
          				? this.dependTypes[typeof param](param, element)
          				: true;
          		},
          	
          		dependTypes: {
          			"boolean": function(param, element) {
          				return param;
          			},
          			"string": function(param, element) {
          				return !!$(param, element.form).length;
          			},
          			"function": function(param, element) {
          				return param(element);
          			}
          		},
          		
          		optional: function(element) {
          			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
          		},
          		
          		startRequest: function(element) {
          			if (!this.pending[element.name]) {
          				this.pendingRequest++;
          				this.pending[element.name] = true;
          			}
          		},
          		
          		stopRequest: function(element, valid) {
          			this.pendingRequest--;
          			// sometimes synchronization fails, make sure pendingRequest is never < 0
          			if (this.pendingRequest < 0)
          				this.pendingRequest = 0;
          			delete this.pending[element.name];
          			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
          				$(this.currentForm).submit();
          				this.formSubmitted = false;
          			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          				this.formSubmitted = false;
          			}
          		},
          		
          		previousValue: function(element) {
          			return $.data(element, "previousValue") || $.data(element, "previousValue", {
          				old: null,
          				valid: true,
          				message: this.defaultMessage( element, "remote" )
          			});
          		}
          		
          	},
          	
          	classRuleSettings: {
          		required: {required: true},
          		email: {email: true},
          		url: {url: true},
          		date: {date: true},
          		dateISO: {dateISO: true},
          		dateDE: {dateDE: true},
          		number: {number: true},
          		numberDE: {numberDE: true},
          		digits: {digits: true},
          		creditcard: {creditcard: true}
          	},
          	
          	addClassRules: function(className, rules) {
          		className.constructor == String ?
          			this.classRuleSettings[className] = rules :
          			$.extend(this.classRuleSettings, className);
          	},
          	
          	classRules: function(element) {
          		var rules = {};
          		var classes = $(element).attr('class');
          		classes && $.each(classes.split(' '), function() {
          			if (this in $.validator.classRuleSettings) {
          				$.extend(rules, $.validator.classRuleSettings[this]);
          			}
          		});
          		return rules;
          	},
          	
          	attributeRules: function(element) {
          		var rules = {};
          		var $element = $(element);
          		
          		for (method in $.validator.methods) {
          			var value = $element.attr(method);
          			if (value) {
          				rules[method] = value;
          			}
          		}
          		
          		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
          		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
          			delete rules.maxlength;
          		}
          		
          		return rules;
          	},
          	
          	metadataRules: function(element) {
          		if (!$.metadata) return {};
          		
          		var meta = $.data(element.form, 'validator').settings.meta;
          		return meta ?
          			$(element).metadata()[meta] :
          			$(element).metadata();
          	},
          	
          	staticRules: function(element) {
          		var rules = {};
          		var validator = $.data(element.form, 'validator');
          		if (validator.settings.rules) {
          			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
          		}
          		return rules;
          	},
          	
          	normalizeRules: function(rules, element) {
          		// handle dependency check
          		$.each(rules, function(prop, val) {
          			// ignore rule when param is explicitly false, eg. required:false
          			if (val === false) {
          				delete rules[prop];
          				return;
          			}
          			if (val.param || val.depends) {
          				var keepRule = true;
          				switch (typeof val.depends) {
          					case "string":
          						keepRule = !!$(val.depends, element.form).length;
          						break;
          					case "function":
          						keepRule = val.depends.call(element, element);
          						break;
          				}
          				if (keepRule) {
          					rules[prop] = val.param !== undefined ? val.param : true;
          				} else {
          					delete rules[prop];
          				}
          			}
          		});
          		
          		// evaluate parameters
          		$.each(rules, function(rule, parameter) {
          			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
          		});
          		
          		// clean number parameters
          		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
          			if (rules[this]) {
          				rules[this] = Number(rules[this]);
          			}
          		});
          		$.each(['rangelength', 'range'], function() {
          			if (rules[this]) {
          				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
          			}
          		});
          		
          		if ($.validator.autoCreateRanges) {
          			// auto-create ranges
          			if (rules.min && rules.max) {
          				rules.range = [rules.min, rules.max];
          				delete rules.min;
          				delete rules.max;
          			}
          			if (rules.minlength && rules.maxlength) {
          				rules.rangelength = [rules.minlength, rules.maxlength];
          				delete rules.minlength;
          				delete rules.maxlength;
          			}
          		}
          		
          		// To support custom messages in metadata ignore rule methods titled "messages"
          		if (rules.messages) {
          			delete rules.messages;
          		}
          		
          		return rules;
          	},
          	
          	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
          	normalizeRule: function(data) {
          		if( typeof data == "string" ) {
          			var transformed = {};
          			$.each(data.split(/\s/), function() {
          				transformed[this] = true;
          			});
          			data = transformed;
          		}
          		return data;
          	},
          	
          	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
          	addMethod: function(name, method, message) {
          		$.validator.methods[name] = method;
          		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
          		if (method.length < 3) {
          			$.validator.addClassRules(name, $.validator.normalizeRule(name));
          		}
          	},
          
          	methods: {
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/required
          		required: function(value, element, param) {
          			// check if dependency is met
          			if ( !this.depend(param, element) )
          				return "dependency-mismatch";
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				// could be an array for select-multiple or a string, both are fine this way
          				var val = $(element).val();
          				return val && val.length > 0;
          			case 'input':
          				if ( this.checkable(element) )
          					return this.getLength(value, element) > 0;
          			default:
          				return $.trim(value).length > 0;
          			}
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/remote
          		remote: function(value, element, param) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			
          			var previous = this.previousValue(element);
          			if (!this.settings.messages[element.name] )
          				this.settings.messages[element.name] = {};
          			previous.originalMessage = this.settings.messages[element.name].remote;
          			this.settings.messages[element.name].remote = previous.message;
          			
          			param = typeof param == "string" && {url:param} || param; 
          			
          			if ( previous.old !== value ) {
          				previous.old = value;
          				var validator = this;
          				this.startRequest(element);
          				var data = {};
          				data[element.name] = value;
          				$.ajax($.extend(true, {
          					url: param,
          					mode: "abort",
          					port: "validate" + element.name,
          					dataType: "json",
          					data: data,
          					success: function(response) {
          						validator.settings.messages[element.name].remote = previous.originalMessage;
          						var valid = response === true;
          						if ( valid ) {
          							var submitted = validator.formSubmitted;
          							validator.prepareElement(element);
          							validator.formSubmitted = submitted;
          							validator.successList.push(element);
          							validator.showErrors();
          						} else {
          							var errors = {};
          							var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
          							errors[element.name] = $.isFunction(message) ? message(value) : message;
          							validator.showErrors(errors);
          						}
          						previous.valid = valid;
          						validator.stopRequest(element, valid);
          					}
          				}, param));
          				return "pending";
          			} else if( this.pending[element.name] ) {
          				return "pending";
          			}
          			return previous.valid;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
          		minlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
          		maxlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
          		rangelength: function(value, element, param) {
          			var length = this.getLength($.trim(value), element);
          			return this.optional(element) || ( length >= param[0] && length <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/min
          		min: function( value, element, param ) {
          			return this.optional(element) || value >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/max
          		max: function( value, element, param ) {
          			return this.optional(element) || value <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/range
          		range: function( value, element, param ) {
          			return this.optional(element) || ( value >= param[0] && value <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/email
          		email: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
          			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/url
          		url: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
          			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
          		},
                  
          		// http://docs.jquery.com/Plugins/Validation/Methods/date
          		date: function(value, element) {
          			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
          		dateISO: function(value, element) {
          			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/number
          		number: function(value, element) {
          			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/digits
          		digits: function(value, element) {
          			return this.optional(element) || /^\d+$/.test(value);
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
          		// based on http://en.wikipedia.org/wiki/Luhn
          		creditcard: function(value, element) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			// accept only digits and dashes
          			if (/[^0-9-]+/.test(value))
          				return false;
          			var nCheck = 0,
          				nDigit = 0,
          				bEven = false;
          
          			value = value.replace(/\D/g, "");
          
          			for (var n = value.length - 1; n >= 0; n--) {
          				var cDigit = value.charAt(n);
          				var nDigit = parseInt(cDigit, 10);
          				if (bEven) {
          					if ((nDigit *= 2) > 9)
          						nDigit -= 9;
          				}
          				nCheck += nDigit;
          				bEven = !bEven;
          			}
          
          			return (nCheck % 10) == 0;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/accept
          		accept: function(value, element, param) {
          			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
          			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
          		equalTo: function(value, element, param) {
          			// bind to the blur event of the target in order to revalidate whenever the target field is updated
          			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
          			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
          				$(element).valid();
          			});
          			return value == target.val();
          		}
          		
          	}
          	
          });
          
          // deprecated, use $.validator.format instead
          $.format = $.validator.format;
          
          })(jQuery);
          
          // ajax mode: abort
          // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
          // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
          ;(function($) {
          	var ajax = $.ajax;
          	var pendingRequests = {};
          	$.ajax = function(settings) {
          		// create settings for compatibility with ajaxSetup
          		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
          		var port = settings.port;
          		if (settings.mode == "abort") {
          			if ( pendingRequests[port] ) {
          				pendingRequests[port].abort();
          			}
          			return (pendingRequests[port] = ajax.apply(this, arguments));
          		}
          		return ajax.apply(this, arguments);
          	};
          })(jQuery);
          
          // provides cross-browser focusin and focusout events
          // IE has native support, in other browsers, use event caputuring (neither bubbles)
          
          // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
          // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
          ;(function($) {
          	// only implement if not provided by jQuery core (since 1.4)
          	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
          	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
          		$.each({
          			focus: 'focusin',
          			blur: 'focusout'	
          		}, function( original, fix ){
          			$.event.special[fix] = {
          				setup:function() {
          					this.addEventListener( original, handler, true );
          				},
          				teardown:function() {
          					this.removeEventListener( original, handler, true );
          				},
          				handler: function(e) {
          					arguments[0] = $.event.fix(e);
          					arguments[0].type = fix;
          					return $.event.handle.apply(this, arguments);
          				}
          			};
          			function handler(e) {
          				e = $.event.fix(e);
          				e.type = fix;
          				return $.event.handle.call(this, e);
          			}
          		});
          	};
          	$.extend($.fn, {
          		validateDelegate: function(delegate, type, handler) {
          			return this.bind(type, function(event) {
          				var target = $(event.target);
          				if (target.is(delegate)) {
          					return handler.apply(target, arguments);
          				}
          			});
          		}
          	});
          })(jQuery);
          
          Evidence
          select
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        21. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bTODO\b and was detected 2 times, the first in the element starting with: " // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (397 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery-validate/jquery.validate.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 37133
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"37133-1268175436000"
          Last-Modified: Tue, 09 Mar 2010 22:57:16 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (37133 bytes)
          /*
           * jQuery validation plug-in 1.7
           *
           * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
           * http://docs.jquery.com/Plugins/Validation
           *
           * Copyright (c) 2006 - 2008 Jörn Zaefferer
           *
           * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          $.extend($.fn, {
          	// http://docs.jquery.com/Plugins/Validation/validate
          	validate: function( options ) {
          
          		// if nothing is selected, return nothing; can't chain anyway
          		if (!this.length) {
          			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
          			return;
          		}
          
          		// check if a validator for this form was already created
          		var validator = $.data(this[0], 'validator');
          		if ( validator ) {
          			return validator;
          		}
          		
          		validator = new $.validator( options, this[0] );
          		$.data(this[0], 'validator', validator); 
          		
          		if ( validator.settings.onsubmit ) {
          		
          			// allow suppresing validation by adding a cancel class to the submit button
          			this.find("input, button").filter(".cancel").click(function() {
          				validator.cancelSubmit = true;
          			});
          			
          			// when a submitHandler is used, capture the submitting button
          			if (validator.settings.submitHandler) {
          				this.find("input, button").filter(":submit").click(function() {
          					validator.submitButton = this;
          				});
          			}
          		
          			// validate the form on submit
          			this.submit( function( event ) {
          				if ( validator.settings.debug )
          					// prevent form submit to be able to see console output
          					event.preventDefault();
          					
          				function handle() {
          					if ( validator.settings.submitHandler ) {
          						if (validator.submitButton) {
          							// insert a hidden input as a replacement for the missing submit button
          							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
          						}
          						validator.settings.submitHandler.call( validator, validator.currentForm );
          						if (validator.submitButton) {
          							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
          							hidden.remove();
          						}
          						return false;
          					}
          					return true;
          				}
          					
          				// prevent submit for invalid forms or custom submit handlers
          				if ( validator.cancelSubmit ) {
          					validator.cancelSubmit = false;
          					return handle();
          				}
          				if ( validator.form() ) {
          					if ( validator.pendingRequest ) {
          						validator.formSubmitted = true;
          						return false;
          					}
          					return handle();
          				} else {
          					validator.focusInvalid();
          					return false;
          				}
          			});
          		}
          		
          		return validator;
          	},
          	// http://docs.jquery.com/Plugins/Validation/valid
          	valid: function() {
                  if ( $(this[0]).is('form')) {
                      return this.validate().form();
                  } else {
                      var valid = true;
                      var validator = $(this[0].form).validate();
                      this.each(function() {
          				valid &= validator.element(this);
                      });
                      return valid;
                  }
              },
          	// attributes: space seperated list of attributes to retrieve and remove
          	removeAttrs: function(attributes) {
          		var result = {},
          			$element = this;
          		$.each(attributes.split(/\s/), function(index, value) {
          			result[value] = $element.attr(value);
          			$element.removeAttr(value);
          		});
          		return result;
          	},
          	// http://docs.jquery.com/Plugins/Validation/rules
          	rules: function(command, argument) {
          		var element = this[0];
          		
          		if (command) {
          			var settings = $.data(element.form, 'validator').settings;
          			var staticRules = settings.rules;
          			var existingRules = $.validator.staticRules(element);
          			switch(command) {
          			case "add":
          				$.extend(existingRules, $.validator.normalizeRule(argument));
          				staticRules[element.name] = existingRules;
          				if (argument.messages)
          					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
          				break;
          			case "remove":
          				if (!argument) {
          					delete staticRules[element.name];
          					return existingRules;
          				}
          				var filtered = {};
          				$.each(argument.split(/\s/), function(index, method) {
          					filtered[method] = existingRules[method];
          					delete existingRules[method];
          				});
          				return filtered;
          			}
          		}
          		
          		var data = $.validator.normalizeRules(
          		$.extend(
          			{},
          			$.validator.metadataRules(element),
          			$.validator.classRules(element),
          			$.validator.attributeRules(element),
          			$.validator.staticRules(element)
          		), element);
          		
          		// make sure required is at front
          		if (data.required) {
          			var param = data.required;
          			delete data.required;
          			data = $.extend({required: param}, data);
          		}
          		
          		return data;
          	}
          });
          
          // Custom selectors
          $.extend($.expr[":"], {
          	// http://docs.jquery.com/Plugins/Validation/blank
          	blank: function(a) {return !$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/filled
          	filled: function(a) {return !!$.trim("" + a.value);},
          	// http://docs.jquery.com/Plugins/Validation/unchecked
          	unchecked: function(a) {return !a.checked;}
          });
          
          // constructor for validator
          $.validator = function( options, form ) {
          	this.settings = $.extend( true, {}, $.validator.defaults, options );
          	this.currentForm = form;
          	this.init();
          };
          
          $.validator.format = function(source, params) {
          	if ( arguments.length == 1 ) 
          		return function() {
          			var args = $.makeArray(arguments);
          			args.unshift(source);
          			return $.validator.format.apply( this, args );
          		};
          	if ( arguments.length > 2 && params.constructor != Array  ) {
          		params = $.makeArray(arguments).slice(1);
          	}
          	if ( params.constructor != Array ) {
          		params = [ params ];
          	}
          	$.each(params, function(i, n) {
          		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
          	});
          	return source;
          };
          
          $.extend($.validator, {
          	
          	defaults: {
          		messages: {},
          		groups: {},
          		rules: {},
          		errorClass: "error",
          		validClass: "valid",
          		errorElement: "label",
          		focusInvalid: true,
          		errorContainer: $( [] ),
          		errorLabelContainer: $( [] ),
          		onsubmit: true,
          		ignore: [],
          		ignoreTitle: false,
          		onfocusin: function(element) {
          			this.lastActive = element;
          				
          			// hide error label and remove error class on focus if enabled
          			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
          				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
          				this.errorsFor(element).hide();
          			}
          		},
          		onfocusout: function(element) {
          			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
          				this.element(element);
          			}
          		},
          		onkeyup: function(element) {
          			if ( element.name in this.submitted || element == this.lastElement ) {
          				this.element(element);
          			}
          		},
          		onclick: function(element) {
          			// click on selects, radiobuttons and checkboxes
          			if ( element.name in this.submitted )
          				this.element(element);
          			// or option elements, check parent select in that case
          			else if (element.parentNode.name in this.submitted)
          				this.element(element.parentNode);
          		},
          		highlight: function( element, errorClass, validClass ) {
          			$(element).addClass(errorClass).removeClass(validClass);
          		},
          		unhighlight: function( element, errorClass, validClass ) {
          			$(element).removeClass(errorClass).addClass(validClass);
          		}
          	},
          
          	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
          	setDefaults: function(settings) {
          		$.extend( $.validator.defaults, settings );
          	},
          
          	messages: {
          		required: "This field is required.",
          		remote: "Please fix this field.",
          		email: "Please enter a valid email address.",
          		url: "Please enter a valid URL.",
          		date: "Please enter a valid date.",
          		dateISO: "Please enter a valid date (ISO).",
          		number: "Please enter a valid number.",
          		digits: "Please enter only digits.",
          		creditcard: "Please enter a valid credit card number.",
          		equalTo: "Please enter the same value again.",
          		accept: "Please enter a value with a valid extension.",
          		maxlength: $.validator.format("Please enter no more than {0} characters."),
          		minlength: $.validator.format("Please enter at least {0} characters."),
          		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
          		range: $.validator.format("Please enter a value between {0} and {1}."),
          		max: $.validator.format("Please enter a value less than or equal to {0}."),
          		min: $.validator.format("Please enter a value greater than or equal to {0}.")
          	},
          	
          	autoCreateRanges: false,
          	
          	prototype: {
          		
          		init: function() {
          			this.labelContainer = $(this.settings.errorLabelContainer);
          			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
          			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
          			this.submitted = {};
          			this.valueCache = {};
          			this.pendingRequest = 0;
          			this.pending = {};
          			this.invalid = {};
          			this.reset();
          			
          			var groups = (this.groups = {});
          			$.each(this.settings.groups, function(key, value) {
          				$.each(value.split(/\s/), function(index, name) {
          					groups[name] = key;
          				});
          			});
          			var rules = this.settings.rules;
          			$.each(rules, function(key, value) {
          				rules[key] = $.validator.normalizeRule(value);
          			});
          			
          			function delegate(event) {
          				var validator = $.data(this[0].form, "validator"),
          					eventType = "on" + event.type.replace(/^validate/, "");
          				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
          			}
          			$(this.currentForm)
          				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
          				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);
          
          			if (this.settings.invalidHandler)
          				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/form
          		form: function() {
          			this.checkForm();
          			$.extend(this.submitted, this.errorMap);
          			this.invalid = $.extend({}, this.errorMap);
          			if (!this.valid())
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          			this.showErrors();
          			return this.valid();
          		},
          		
          		checkForm: function() {
          			this.prepareForm();
          			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
          				this.check( elements[i] );
          			}
          			return this.valid(); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/element
          		element: function( element ) {
          			element = this.clean( element );
          			this.lastElement = element;
          			this.prepareElement( element );
          			this.currentElements = $(element);
          			var result = this.check( element );
          			if ( result ) {
          				delete this.invalid[element.name];
          			} else {
          				this.invalid[element.name] = true;
          			}
          			if ( !this.numberOfInvalids() ) {
          				// Hide error containers on last error
          				this.toHide = this.toHide.add( this.containers );
          			}
          			this.showErrors();
          			return result;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
          		showErrors: function(errors) {
          			if(errors) {
          				// add items to error list and map
          				$.extend( this.errorMap, errors );
          				this.errorList = [];
          				for ( var name in errors ) {
          					this.errorList.push({
          						message: errors[name],
          						element: this.findByName(name)[0]
          					});
          				}
          				// remove items from success list
          				this.successList = $.grep( this.successList, function(element) {
          					return !(element.name in errors);
          				});
          			}
          			this.settings.showErrors
          				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
          				: this.defaultShowErrors();
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
          		resetForm: function() {
          			if ( $.fn.resetForm )
          				$( this.currentForm ).resetForm();
          			this.submitted = {};
          			this.prepareForm();
          			this.hideErrors();
          			this.elements().removeClass( this.settings.errorClass );
          		},
          		
          		numberOfInvalids: function() {
          			return this.objectLength(this.invalid);
          		},
          		
          		objectLength: function( obj ) {
          			var count = 0;
          			for ( var i in obj )
          				count++;
          			return count;
          		},
          		
          		hideErrors: function() {
          			this.addWrapper( this.toHide ).hide();
          		},
          		
          		valid: function() {
          			return this.size() == 0;
          		},
          		
          		size: function() {
          			return this.errorList.length;
          		},
          		
          		focusInvalid: function() {
          			if( this.settings.focusInvalid ) {
          				try {
          					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
          					.filter(":visible")
          					.focus()
          					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
          					.trigger("focusin");
          				} catch(e) {
          					// ignore IE throwing errors when focusing hidden elements
          				}
          			}
          		},
          		
          		findLastActive: function() {
          			var lastActive = this.lastActive;
          			return lastActive && $.grep(this.errorList, function(n) {
          				return n.element.name == lastActive.name;
          			}).length == 1 && lastActive;
          		},
          		
          		elements: function() {
          			var validator = this,
          				rulesCache = {};
          			
          			// select all valid inputs inside the form (no submit or reset buttons)
          			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
          			return $([]).add(this.currentForm.elements)
          			.filter(":input")
          			.not(":submit, :reset, :image, [disabled]")
          			.not( this.settings.ignore )
          			.filter(function() {
          				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
          			
          				// select only the first element for each name, and only those with rules specified
          				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
          					return false;
          				
          				rulesCache[this.name] = true;
          				return true;
          			});
          		},
          		
          		clean: function( selector ) {
          			return $( selector )[0];
          		},
          		
          		errors: function() {
          			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
          		},
          		
          		reset: function() {
          			this.successList = [];
          			this.errorList = [];
          			this.errorMap = {};
          			this.toShow = $([]);
          			this.toHide = $([]);
          			this.currentElements = $([]);
          		},
          		
          		prepareForm: function() {
          			this.reset();
          			this.toHide = this.errors().add( this.containers );
          		},
          		
          		prepareElement: function( element ) {
          			this.reset();
          			this.toHide = this.errorsFor(element);
          		},
          	
          		check: function( element ) {
          			element = this.clean( element );
          			
          			// if radio/checkbox, validate first element in group instead
          			if (this.checkable(element)) {
          				element = this.findByName( element.name )[0];
          			}
          			
          			var rules = $(element).rules();
          			var dependencyMismatch = false;
          			for( method in rules ) {
          				var rule = { method: method, parameters: rules[method] };
          				try {
          					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
          					
          					// if a method indicates that the field is optional and therefore valid,
          					// don't mark it as valid when there are no other rules
          					if ( result == "dependency-mismatch" ) {
          						dependencyMismatch = true;
          						continue;
          					}
          					dependencyMismatch = false;
          					
          					if ( result == "pending" ) {
          						this.toHide = this.toHide.not( this.errorsFor(element) );
          						return;
          					}
          					
          					if( !result ) {
          						this.formatAndAdd( element, rule );
          						return false;
          					}
          				} catch(e) {
          					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
          						 + ", check the '" + rule.method + "' method", e);
          					throw e;
          				}
          			}
          			if (dependencyMismatch)
          				return;
          			if ( this.objectLength(rules) )
          				this.successList.push(element);
          			return true;
          		},
          		
          		// return the custom message for the given element and validation method
          		// specified in the element's "messages" metadata
          		customMetaMessage: function(element, method) {
          			if (!$.metadata)
          				return;
          			
          			var meta = this.settings.meta
          				? $(element).metadata()[this.settings.meta]
          				: $(element).metadata();
          			
          			return meta && meta.messages && meta.messages[method];
          		},
          		
          		// return the custom message for the given element name and validation method
          		customMessage: function( name, method ) {
          			var m = this.settings.messages[name];
          			return m && (m.constructor == String
          				? m
          				: m[method]);
          		},
          		
          		// return the first defined argument, allowing empty strings
          		findDefined: function() {
          			for(var i = 0; i < arguments.length; i++) {
          				if (arguments[i] !== undefined)
          					return arguments[i];
          			}
          			return undefined;
          		},
          		
          		defaultMessage: function( element, method) {
          			return this.findDefined(
          				this.customMessage( element.name, method ),
          				this.customMetaMessage( element, method ),
          				// title is never undefined, so handle empty string as undefined
          				!this.settings.ignoreTitle && element.title || undefined,
          				$.validator.messages[method],
          				"<strong>Warning: No message defined for " + element.name + "</strong>"
          			);
          		},
          		
          		formatAndAdd: function( element, rule ) {
          			var message = this.defaultMessage( element, rule.method ),
          				theregex = /\$?\{(\d+)\}/g;
          			if ( typeof message == "function" ) {
          				message = message.call(this, rule.parameters, element);
          			} else if (theregex.test(message)) {
          				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
          			}			
          			this.errorList.push({
          				message: message,
          				element: element
          			});
          			
          			this.errorMap[element.name] = message;
          			this.submitted[element.name] = message;
          		},
          		
          		addWrapper: function(toToggle) {
          			if ( this.settings.wrapper )
          				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
          			return toToggle;
          		},
          		
          		defaultShowErrors: function() {
          			for ( var i = 0; this.errorList[i]; i++ ) {
          				var error = this.errorList[i];
          				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
          				this.showLabel( error.element, error.message );
          			}
          			if( this.errorList.length ) {
          				this.toShow = this.toShow.add( this.containers );
          			}
          			if (this.settings.success) {
          				for ( var i = 0; this.successList[i]; i++ ) {
          					this.showLabel( this.successList[i] );
          				}
          			}
          			if (this.settings.unhighlight) {
          				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
          					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
          				}
          			}
          			this.toHide = this.toHide.not( this.toShow );
          			this.hideErrors();
          			this.addWrapper( this.toShow ).show();
          		},
          		
          		validElements: function() {
          			return this.currentElements.not(this.invalidElements());
          		},
          		
          		invalidElements: function() {
          			return $(this.errorList).map(function() {
          				return this.element;
          			});
          		},
          		
          		showLabel: function(element, message) {
          			var label = this.errorsFor( element );
          			if ( label.length ) {
          				// refresh error/success class
          				label.removeClass().addClass( this.settings.errorClass );
          			
          				// check if we have a generated label, replace the message then
          				label.attr("generated") && label.html(message);
          			} else {
          				// create label
          				label = $("<" + this.settings.errorElement + "/>")
          					.attr({"for":  this.idOrName(element), generated: true})
          					.addClass(this.settings.errorClass)
          					.html(message || "");
          				if ( this.settings.wrapper ) {
          					// make sure the element is visible, even in IE
          					// actually showing the wrapped element is handled elsewhere
          					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
          				}
          				if ( !this.labelContainer.append(label).length )
          					this.settings.errorPlacement
          						? this.settings.errorPlacement(label, $(element) )
          						: label.insertAfter(element);
          			}
          			if ( !message && this.settings.success ) {
          				label.text("");
          				typeof this.settings.success == "string"
          					? label.addClass( this.settings.success )
          					: this.settings.success( label );
          			}
          			this.toShow = this.toShow.add(label);
          		},
          		
          		errorsFor: function(element) {
          			var name = this.idOrName(element);
              		return this.errors().filter(function() {
          				return $(this).attr('for') == name;
          			});
          		},
          		
          		idOrName: function(element) {
          			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
          		},
          
          		checkable: function( element ) {
          			return /radio|checkbox/i.test(element.type);
          		},
          		
          		findByName: function( name ) {
          			// select by name and filter by form for performance over form.find("[name=...]")
          			var form = this.currentForm;
          			return $(document.getElementsByName(name)).map(function(index, element) {
          				return element.form == form && element.name == name && element  || null;
          			});
          		},
          		
          		getLength: function(value, element) {
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				return $("option:selected", element).length;
          			case 'input':
          				if( this.checkable( element) )
          					return this.findByName(element.name).filter(':checked').length;
          			}
          			return value.length;
          		},
          	
          		depend: function(param, element) {
          			return this.dependTypes[typeof param]
          				? this.dependTypes[typeof param](param, element)
          				: true;
          		},
          	
          		dependTypes: {
          			"boolean": function(param, element) {
          				return param;
          			},
          			"string": function(param, element) {
          				return !!$(param, element.form).length;
          			},
          			"function": function(param, element) {
          				return param(element);
          			}
          		},
          		
          		optional: function(element) {
          			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
          		},
          		
          		startRequest: function(element) {
          			if (!this.pending[element.name]) {
          				this.pendingRequest++;
          				this.pending[element.name] = true;
          			}
          		},
          		
          		stopRequest: function(element, valid) {
          			this.pendingRequest--;
          			// sometimes synchronization fails, make sure pendingRequest is never < 0
          			if (this.pendingRequest < 0)
          				this.pendingRequest = 0;
          			delete this.pending[element.name];
          			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
          				$(this.currentForm).submit();
          				this.formSubmitted = false;
          			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
          				$(this.currentForm).triggerHandler("invalid-form", [this]);
          				this.formSubmitted = false;
          			}
          		},
          		
          		previousValue: function(element) {
          			return $.data(element, "previousValue") || $.data(element, "previousValue", {
          				old: null,
          				valid: true,
          				message: this.defaultMessage( element, "remote" )
          			});
          		}
          		
          	},
          	
          	classRuleSettings: {
          		required: {required: true},
          		email: {email: true},
          		url: {url: true},
          		date: {date: true},
          		dateISO: {dateISO: true},
          		dateDE: {dateDE: true},
          		number: {number: true},
          		numberDE: {numberDE: true},
          		digits: {digits: true},
          		creditcard: {creditcard: true}
          	},
          	
          	addClassRules: function(className, rules) {
          		className.constructor == String ?
          			this.classRuleSettings[className] = rules :
          			$.extend(this.classRuleSettings, className);
          	},
          	
          	classRules: function(element) {
          		var rules = {};
          		var classes = $(element).attr('class');
          		classes && $.each(classes.split(' '), function() {
          			if (this in $.validator.classRuleSettings) {
          				$.extend(rules, $.validator.classRuleSettings[this]);
          			}
          		});
          		return rules;
          	},
          	
          	attributeRules: function(element) {
          		var rules = {};
          		var $element = $(element);
          		
          		for (method in $.validator.methods) {
          			var value = $element.attr(method);
          			if (value) {
          				rules[method] = value;
          			}
          		}
          		
          		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
          		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
          			delete rules.maxlength;
          		}
          		
          		return rules;
          	},
          	
          	metadataRules: function(element) {
          		if (!$.metadata) return {};
          		
          		var meta = $.data(element.form, 'validator').settings.meta;
          		return meta ?
          			$(element).metadata()[meta] :
          			$(element).metadata();
          	},
          	
          	staticRules: function(element) {
          		var rules = {};
          		var validator = $.data(element.form, 'validator');
          		if (validator.settings.rules) {
          			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
          		}
          		return rules;
          	},
          	
          	normalizeRules: function(rules, element) {
          		// handle dependency check
          		$.each(rules, function(prop, val) {
          			// ignore rule when param is explicitly false, eg. required:false
          			if (val === false) {
          				delete rules[prop];
          				return;
          			}
          			if (val.param || val.depends) {
          				var keepRule = true;
          				switch (typeof val.depends) {
          					case "string":
          						keepRule = !!$(val.depends, element.form).length;
          						break;
          					case "function":
          						keepRule = val.depends.call(element, element);
          						break;
          				}
          				if (keepRule) {
          					rules[prop] = val.param !== undefined ? val.param : true;
          				} else {
          					delete rules[prop];
          				}
          			}
          		});
          		
          		// evaluate parameters
          		$.each(rules, function(rule, parameter) {
          			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
          		});
          		
          		// clean number parameters
          		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
          			if (rules[this]) {
          				rules[this] = Number(rules[this]);
          			}
          		});
          		$.each(['rangelength', 'range'], function() {
          			if (rules[this]) {
          				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
          			}
          		});
          		
          		if ($.validator.autoCreateRanges) {
          			// auto-create ranges
          			if (rules.min && rules.max) {
          				rules.range = [rules.min, rules.max];
          				delete rules.min;
          				delete rules.max;
          			}
          			if (rules.minlength && rules.maxlength) {
          				rules.rangelength = [rules.minlength, rules.maxlength];
          				delete rules.minlength;
          				delete rules.maxlength;
          			}
          		}
          		
          		// To support custom messages in metadata ignore rule methods titled "messages"
          		if (rules.messages) {
          			delete rules.messages;
          		}
          		
          		return rules;
          	},
          	
          	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
          	normalizeRule: function(data) {
          		if( typeof data == "string" ) {
          			var transformed = {};
          			$.each(data.split(/\s/), function() {
          				transformed[this] = true;
          			});
          			data = transformed;
          		}
          		return data;
          	},
          	
          	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
          	addMethod: function(name, method, message) {
          		$.validator.methods[name] = method;
          		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
          		if (method.length < 3) {
          			$.validator.addClassRules(name, $.validator.normalizeRule(name));
          		}
          	},
          
          	methods: {
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/required
          		required: function(value, element, param) {
          			// check if dependency is met
          			if ( !this.depend(param, element) )
          				return "dependency-mismatch";
          			switch( element.nodeName.toLowerCase() ) {
          			case 'select':
          				// could be an array for select-multiple or a string, both are fine this way
          				var val = $(element).val();
          				return val && val.length > 0;
          			case 'input':
          				if ( this.checkable(element) )
          					return this.getLength(value, element) > 0;
          			default:
          				return $.trim(value).length > 0;
          			}
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/remote
          		remote: function(value, element, param) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			
          			var previous = this.previousValue(element);
          			if (!this.settings.messages[element.name] )
          				this.settings.messages[element.name] = {};
          			previous.originalMessage = this.settings.messages[element.name].remote;
          			this.settings.messages[element.name].remote = previous.message;
          			
          			param = typeof param == "string" && {url:param} || param; 
          			
          			if ( previous.old !== value ) {
          				previous.old = value;
          				var validator = this;
          				this.startRequest(element);
          				var data = {};
          				data[element.name] = value;
          				$.ajax($.extend(true, {
          					url: param,
          					mode: "abort",
          					port: "validate" + element.name,
          					dataType: "json",
          					data: data,
          					success: function(response) {
          						validator.settings.messages[element.name].remote = previous.originalMessage;
          						var valid = response === true;
          						if ( valid ) {
          							var submitted = validator.formSubmitted;
          							validator.prepareElement(element);
          							validator.formSubmitted = submitted;
          							validator.successList.push(element);
          							validator.showErrors();
          						} else {
          							var errors = {};
          							var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
          							errors[element.name] = $.isFunction(message) ? message(value) : message;
          							validator.showErrors(errors);
          						}
          						previous.valid = valid;
          						validator.stopRequest(element, valid);
          					}
          				}, param));
          				return "pending";
          			} else if( this.pending[element.name] ) {
          				return "pending";
          			}
          			return previous.valid;
          		},
          
          		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
          		minlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
          		maxlength: function(value, element, param) {
          			return this.optional(element) || this.getLength($.trim(value), element) <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
          		rangelength: function(value, element, param) {
          			var length = this.getLength($.trim(value), element);
          			return this.optional(element) || ( length >= param[0] && length <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/min
          		min: function( value, element, param ) {
          			return this.optional(element) || value >= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/max
          		max: function( value, element, param ) {
          			return this.optional(element) || value <= param;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/range
          		range: function( value, element, param ) {
          			return this.optional(element) || ( value >= param[0] && value <= param[1] );
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/email
          		email: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
          			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/url
          		url: function(value, element) {
          			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
          			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
          		},
                  
          		// http://docs.jquery.com/Plugins/Validation/Methods/date
          		date: function(value, element) {
          			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
          		dateISO: function(value, element) {
          			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/number
          		number: function(value, element) {
          			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
          		},
          	
          		// http://docs.jquery.com/Plugins/Validation/Methods/digits
          		digits: function(value, element) {
          			return this.optional(element) || /^\d+$/.test(value);
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
          		// based on http://en.wikipedia.org/wiki/Luhn
          		creditcard: function(value, element) {
          			if ( this.optional(element) )
          				return "dependency-mismatch";
          			// accept only digits and dashes
          			if (/[^0-9-]+/.test(value))
          				return false;
          			var nCheck = 0,
          				nDigit = 0,
          				bEven = false;
          
          			value = value.replace(/\D/g, "");
          
          			for (var n = value.length - 1; n >= 0; n--) {
          				var cDigit = value.charAt(n);
          				var nDigit = parseInt(cDigit, 10);
          				if (bEven) {
          					if ((nDigit *= 2) > 9)
          						nDigit -= 9;
          				}
          				nCheck += nDigit;
          				bEven = !bEven;
          			}
          
          			return (nCheck % 10) == 0;
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/accept
          		accept: function(value, element, param) {
          			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
          			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
          		},
          		
          		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
          		equalTo: function(value, element, param) {
          			// bind to the blur event of the target in order to revalidate whenever the target field is updated
          			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
          			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
          				$(element).valid();
          			});
          			return value == target.val();
          		}
          		
          	}
          	
          });
          
          // deprecated, use $.validator.format instead
          $.format = $.validator.format;
          
          })(jQuery);
          
          // ajax mode: abort
          // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
          // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
          ;(function($) {
          	var ajax = $.ajax;
          	var pendingRequests = {};
          	$.ajax = function(settings) {
          		// create settings for compatibility with ajaxSetup
          		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
          		var port = settings.port;
          		if (settings.mode == "abort") {
          			if ( pendingRequests[port] ) {
          				pendingRequests[port].abort();
          			}
          			return (pendingRequests[port] = ajax.apply(this, arguments));
          		}
          		return ajax.apply(this, arguments);
          	};
          })(jQuery);
          
          // provides cross-browser focusin and focusout events
          // IE has native support, in other browsers, use event caputuring (neither bubbles)
          
          // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
          // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
          ;(function($) {
          	// only implement if not provided by jQuery core (since 1.4)
          	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
          	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
          		$.each({
          			focus: 'focusin',
          			blur: 'focusout'	
          		}, function( original, fix ){
          			$.event.special[fix] = {
          				setup:function() {
          					this.addEventListener( original, handler, true );
          				},
          				teardown:function() {
          					this.removeEventListener( original, handler, true );
          				},
          				handler: function(e) {
          					arguments[0] = $.event.fix(e);
          					arguments[0].type = fix;
          					return $.event.handle.apply(this, arguments);
          				}
          			};
          			function handler(e) {
          				e = $.event.fix(e);
          				e.type = fix;
          				return $.event.handle.call(this, e);
          			}
          		});
          	};
          	$.extend($.fn, {
          		validateDelegate: function(delegate, type, handler) {
          			return this.bind(type, function(event) {
          				var target = $(event.target);
          				if (target.is(delegate)) {
          					return handler.apply(target, arguments);
          				}
          			});
          		}
          	});
          })(jQuery);
          
          Evidence
          TODO
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        22. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bBUG\b and was detected in the element starting with: "// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (393 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 10254
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10254-1268025194000"
          Last-Modified: Mon, 08 Mar 2010 05:13:14 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10254 bytes)
          /*!
           * jQuery throttle / debounce - v1.1 - 3/7/2010
           * http://benalman.com/projects/jquery-throttle-debounce-plugin/
           * 
           * Copyright (c) 2010 "Cowboy" Ben Alman
           * Dual licensed under the MIT and GPL licenses.
           * http://benalman.com/about/license/
           */
          
          // Script: jQuery throttle / debounce: Sometimes, less is more!
          //
          // *Version: 1.1, Last updated: 3/7/2010*
          // 
          // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
          // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
          // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
          // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
          // 
          // About: License
          // 
          // Copyright (c) 2010 "Cowboy" Ben Alman,
          // Dual licensed under the MIT and GPL licenses.
          // http://benalman.com/about/license/
          // 
          // About: Examples
          // 
          // These working examples, complete with fully commented code, illustrate a few
          // ways in which this plugin can be used.
          // 
          // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
          // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
          // 
          // About: Support and Testing
          // 
          // Information about what version or versions of jQuery this plugin has been
          // tested with, what browsers it has been tested in, and where the unit tests
          // reside (so you can test it yourself).
          // 
          // jQuery Versions - none, 1.3.2, 1.4.2
          // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
          // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
          // 
          // About: Release History
          // 
          // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
          //       executed later than they should. Reworked a fair amount of internal
          //       logic as well.
          // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
          //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
          //       no_trailing throttle parameter and debounce functionality.
          // 
          // Topic: Note for non-jQuery users
          // 
          // jQuery isn't actually required for this plugin, because nothing internal
          // uses any jQuery methods or properties. jQuery is just used as a namespace
          // under which these methods can exist.
          // 
          // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
          // when this plugin is loaded, the method described below will be created in
          // the `Cowboy` namespace. Usage will be exactly the same, but instead of
          // $.method() or jQuery.method(), you'll need to use Cowboy.method().
          
          (function(window,undefined){
            '$:nomunge'; // Used by YUI compressor.
            
            // Since jQuery really isn't required for this plugin, use `jQuery` as the
            // namespace only if it already exists, otherwise use the `Cowboy` namespace,
            // creating it if necessary.
            var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
              
              // Internal method reference.
              jq_throttle;
            
            // Method: jQuery.throttle
            // 
            // Throttle execution of a function. Especially useful for rate limiting
            // execution of handlers on events like resize and scroll. If you want to
            // rate-limit execution of a function to a single time, see the
            // <jQuery.debounce> method.
            // 
            // In this visualization, | is a throttled-function call and X is the actual
            // callback execution:
            // 
            // > Throttled with `no_trailing` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X    X        X    X    X    X    X    X
            // > 
            // > Throttled with `no_trailing` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X             X    X    X    X    X
            // 
            // Usage:
            // 
            // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', throttled );
            // > jQuery('selector').unbind( 'someevent', throttled );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
            //    true, callback will only execute every `delay` milliseconds while the
            //    throttled-function is being called. If no_trailing is false or
            //    unspecified, callback will be executed one final time after the last
            //    throttled-function call. (After the throttled-function has not been
            //    called for `delay` milliseconds, the internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the throttled-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, throttled, function.
            
            $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
              // After wrapper has stopped being called, this timeout ensures that
              // `callback` is executed at the proper times in `throttle` and `end`
              // debounce modes.
              var timeout_id,
                
                // Keep track of the last time `callback` was executed.
                last_exec = 0;
              
              // `no_trailing` defaults to falsy.
              if ( typeof no_trailing !== 'boolean' ) {
                debounce_mode = callback;
                callback = no_trailing;
                no_trailing = undefined;
              }
              
              // The `wrapper` function encapsulates all of the throttling / debouncing
              // functionality and when executed will limit the rate at which `callback`
              // is executed.
              function wrapper() {
                var that = this,
                  elapsed = +new Date() - last_exec,
                  args = arguments;
                
                // Execute `callback` and update the `last_exec` timestamp.
                function exec() {
                  last_exec = +new Date();
                  callback.apply( that, args );
                };
                
                // If `debounce_mode` is true (at_begin) this is used to clear the flag
                // to allow future `callback` executions.
                function clear() {
                  timeout_id = undefined;
                };
                
                if ( debounce_mode && !timeout_id ) {
                  // Since `wrapper` is being called for the first time and
                  // `debounce_mode` is true (at_begin), execute `callback`.
                  exec();
                }
                
                // Clear any existing timeout.
                timeout_id && clearTimeout( timeout_id );
                
                if ( debounce_mode === undefined && elapsed > delay ) {
                  // In throttle mode, if `delay` time has been exceeded, execute
                  // `callback`.
                  exec();
                  
                } else if ( no_trailing !== true ) {
                  // In trailing throttle mode, since `delay` time has not been
                  // exceeded, schedule `callback` to execute `delay` ms after most
                  // recent execution.
                  // 
                  // If `debounce_mode` is true (at_begin), schedule `clear` to execute
                  // after `delay` ms.
                  // 
                  // If `debounce_mode` is false (at end), schedule `callback` to
                  // execute after `delay` ms.
                  timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
                }
              };
              
              // Set the guid of `wrapper` function to the same of original callback, so
              // it can be removed in jQuery 1.4+ .unbind or .die by using the original
              // callback as a reference.
              if ( $.guid ) {
                wrapper.guid = callback.guid = callback.guid || $.guid++;
              }
              
              // Return the wrapper function.
              return wrapper;
            };
            
            // Method: jQuery.debounce
            // 
            // Debounce execution of a function. Debouncing, unlike throttling,
            // guarantees that a function is only executed a single time, either at the
            // very beginning of a series of calls, or at the very end. If you want to
            // simply rate-limit execution of a function, see the <jQuery.throttle>
            // method.
            // 
            // In this visualization, | is a debounced-function call and X is the actual
            // callback execution:
            // 
            // > Debounced with `at_begin` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // >                          X                                 X
            // > 
            // > Debounced with `at_begin` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X                                 X
            // 
            // Usage:
            // 
            // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', debounced );
            // > jQuery('selector').unbind( 'someevent', debounced );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
            //    unspecified, callback will only be executed `delay` milliseconds after
            //    the last debounced-function call. If at_begin is true, callback will be
            //    executed only at the first debounced-function call. (After the
            //    throttled-function has not been called for `delay` milliseconds, the
            //    internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the debounced-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, debounced, function.
            
            $.debounce = function( delay, at_begin, callback ) {
              return callback === undefined
                ? jq_throttle( delay, at_begin, false )
                : jq_throttle( delay, callback, at_begin !== false );
            };
            
          })(this);
          
          Evidence
          bug
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        23. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected in the element starting with: "// from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (393 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 10254
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10254-1268025194000"
          Last-Modified: Mon, 08 Mar 2010 05:13:14 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10254 bytes)
          /*!
           * jQuery throttle / debounce - v1.1 - 3/7/2010
           * http://benalman.com/projects/jquery-throttle-debounce-plugin/
           * 
           * Copyright (c) 2010 "Cowboy" Ben Alman
           * Dual licensed under the MIT and GPL licenses.
           * http://benalman.com/about/license/
           */
          
          // Script: jQuery throttle / debounce: Sometimes, less is more!
          //
          // *Version: 1.1, Last updated: 3/7/2010*
          // 
          // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
          // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
          // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
          // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
          // 
          // About: License
          // 
          // Copyright (c) 2010 "Cowboy" Ben Alman,
          // Dual licensed under the MIT and GPL licenses.
          // http://benalman.com/about/license/
          // 
          // About: Examples
          // 
          // These working examples, complete with fully commented code, illustrate a few
          // ways in which this plugin can be used.
          // 
          // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
          // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
          // 
          // About: Support and Testing
          // 
          // Information about what version or versions of jQuery this plugin has been
          // tested with, what browsers it has been tested in, and where the unit tests
          // reside (so you can test it yourself).
          // 
          // jQuery Versions - none, 1.3.2, 1.4.2
          // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
          // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
          // 
          // About: Release History
          // 
          // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
          //       executed later than they should. Reworked a fair amount of internal
          //       logic as well.
          // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
          //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
          //       no_trailing throttle parameter and debounce functionality.
          // 
          // Topic: Note for non-jQuery users
          // 
          // jQuery isn't actually required for this plugin, because nothing internal
          // uses any jQuery methods or properties. jQuery is just used as a namespace
          // under which these methods can exist.
          // 
          // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
          // when this plugin is loaded, the method described below will be created in
          // the `Cowboy` namespace. Usage will be exactly the same, but instead of
          // $.method() or jQuery.method(), you'll need to use Cowboy.method().
          
          (function(window,undefined){
            '$:nomunge'; // Used by YUI compressor.
            
            // Since jQuery really isn't required for this plugin, use `jQuery` as the
            // namespace only if it already exists, otherwise use the `Cowboy` namespace,
            // creating it if necessary.
            var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
              
              // Internal method reference.
              jq_throttle;
            
            // Method: jQuery.throttle
            // 
            // Throttle execution of a function. Especially useful for rate limiting
            // execution of handlers on events like resize and scroll. If you want to
            // rate-limit execution of a function to a single time, see the
            // <jQuery.debounce> method.
            // 
            // In this visualization, | is a throttled-function call and X is the actual
            // callback execution:
            // 
            // > Throttled with `no_trailing` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X    X        X    X    X    X    X    X
            // > 
            // > Throttled with `no_trailing` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X             X    X    X    X    X
            // 
            // Usage:
            // 
            // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', throttled );
            // > jQuery('selector').unbind( 'someevent', throttled );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
            //    true, callback will only execute every `delay` milliseconds while the
            //    throttled-function is being called. If no_trailing is false or
            //    unspecified, callback will be executed one final time after the last
            //    throttled-function call. (After the throttled-function has not been
            //    called for `delay` milliseconds, the internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the throttled-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, throttled, function.
            
            $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
              // After wrapper has stopped being called, this timeout ensures that
              // `callback` is executed at the proper times in `throttle` and `end`
              // debounce modes.
              var timeout_id,
                
                // Keep track of the last time `callback` was executed.
                last_exec = 0;
              
              // `no_trailing` defaults to falsy.
              if ( typeof no_trailing !== 'boolean' ) {
                debounce_mode = callback;
                callback = no_trailing;
                no_trailing = undefined;
              }
              
              // The `wrapper` function encapsulates all of the throttling / debouncing
              // functionality and when executed will limit the rate at which `callback`
              // is executed.
              function wrapper() {
                var that = this,
                  elapsed = +new Date() - last_exec,
                  args = arguments;
                
                // Execute `callback` and update the `last_exec` timestamp.
                function exec() {
                  last_exec = +new Date();
                  callback.apply( that, args );
                };
                
                // If `debounce_mode` is true (at_begin) this is used to clear the flag
                // to allow future `callback` executions.
                function clear() {
                  timeout_id = undefined;
                };
                
                if ( debounce_mode && !timeout_id ) {
                  // Since `wrapper` is being called for the first time and
                  // `debounce_mode` is true (at_begin), execute `callback`.
                  exec();
                }
                
                // Clear any existing timeout.
                timeout_id && clearTimeout( timeout_id );
                
                if ( debounce_mode === undefined && elapsed > delay ) {
                  // In throttle mode, if `delay` time has been exceeded, execute
                  // `callback`.
                  exec();
                  
                } else if ( no_trailing !== true ) {
                  // In trailing throttle mode, since `delay` time has not been
                  // exceeded, schedule `callback` to execute `delay` ms after most
                  // recent execution.
                  // 
                  // If `debounce_mode` is true (at_begin), schedule `clear` to execute
                  // after `delay` ms.
                  // 
                  // If `debounce_mode` is false (at end), schedule `callback` to
                  // execute after `delay` ms.
                  timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
                }
              };
              
              // Set the guid of `wrapper` function to the same of original callback, so
              // it can be removed in jQuery 1.4+ .unbind or .die by using the original
              // callback as a reference.
              if ( $.guid ) {
                wrapper.guid = callback.guid = callback.guid || $.guid++;
              }
              
              // Return the wrapper function.
              return wrapper;
            };
            
            // Method: jQuery.debounce
            // 
            // Debounce execution of a function. Debouncing, unlike throttling,
            // guarantees that a function is only executed a single time, either at the
            // very beginning of a series of calls, or at the very end. If you want to
            // simply rate-limit execution of a function, see the <jQuery.throttle>
            // method.
            // 
            // In this visualization, | is a debounced-function call and X is the actual
            // callback execution:
            // 
            // > Debounced with `at_begin` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // >                          X                                 X
            // > 
            // > Debounced with `at_begin` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X                                 X
            // 
            // Usage:
            // 
            // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', debounced );
            // > jQuery('selector').unbind( 'someevent', debounced );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
            //    unspecified, callback will only be executed `delay` milliseconds after
            //    the last debounced-function call. If at_begin is true, callback will be
            //    executed only at the first debounced-function call. (After the
            //    throttled-function has not been called for `delay` milliseconds, the
            //    internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the debounced-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, debounced, function.
            
            $.debounce = function( delay, at_begin, callback ) {
              return callback === undefined
                ? jq_throttle( delay, at_begin, false )
                : jq_throttle( delay, callback, at_begin !== false );
            };
            
          })(this);
          
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        24. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bLATER\b and was detected in the element starting with: "// executed later than they should. Reworked a fair amount of internal", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (393 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 10254
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10254-1268025194000"
          Last-Modified: Mon, 08 Mar 2010 05:13:14 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10254 bytes)
          /*!
           * jQuery throttle / debounce - v1.1 - 3/7/2010
           * http://benalman.com/projects/jquery-throttle-debounce-plugin/
           * 
           * Copyright (c) 2010 "Cowboy" Ben Alman
           * Dual licensed under the MIT and GPL licenses.
           * http://benalman.com/about/license/
           */
          
          // Script: jQuery throttle / debounce: Sometimes, less is more!
          //
          // *Version: 1.1, Last updated: 3/7/2010*
          // 
          // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
          // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
          // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
          // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
          // 
          // About: License
          // 
          // Copyright (c) 2010 "Cowboy" Ben Alman,
          // Dual licensed under the MIT and GPL licenses.
          // http://benalman.com/about/license/
          // 
          // About: Examples
          // 
          // These working examples, complete with fully commented code, illustrate a few
          // ways in which this plugin can be used.
          // 
          // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
          // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
          // 
          // About: Support and Testing
          // 
          // Information about what version or versions of jQuery this plugin has been
          // tested with, what browsers it has been tested in, and where the unit tests
          // reside (so you can test it yourself).
          // 
          // jQuery Versions - none, 1.3.2, 1.4.2
          // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
          // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
          // 
          // About: Release History
          // 
          // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
          //       executed later than they should. Reworked a fair amount of internal
          //       logic as well.
          // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
          //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
          //       no_trailing throttle parameter and debounce functionality.
          // 
          // Topic: Note for non-jQuery users
          // 
          // jQuery isn't actually required for this plugin, because nothing internal
          // uses any jQuery methods or properties. jQuery is just used as a namespace
          // under which these methods can exist.
          // 
          // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
          // when this plugin is loaded, the method described below will be created in
          // the `Cowboy` namespace. Usage will be exactly the same, but instead of
          // $.method() or jQuery.method(), you'll need to use Cowboy.method().
          
          (function(window,undefined){
            '$:nomunge'; // Used by YUI compressor.
            
            // Since jQuery really isn't required for this plugin, use `jQuery` as the
            // namespace only if it already exists, otherwise use the `Cowboy` namespace,
            // creating it if necessary.
            var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
              
              // Internal method reference.
              jq_throttle;
            
            // Method: jQuery.throttle
            // 
            // Throttle execution of a function. Especially useful for rate limiting
            // execution of handlers on events like resize and scroll. If you want to
            // rate-limit execution of a function to a single time, see the
            // <jQuery.debounce> method.
            // 
            // In this visualization, | is a throttled-function call and X is the actual
            // callback execution:
            // 
            // > Throttled with `no_trailing` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X    X        X    X    X    X    X    X
            // > 
            // > Throttled with `no_trailing` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X             X    X    X    X    X
            // 
            // Usage:
            // 
            // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', throttled );
            // > jQuery('selector').unbind( 'someevent', throttled );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
            //    true, callback will only execute every `delay` milliseconds while the
            //    throttled-function is being called. If no_trailing is false or
            //    unspecified, callback will be executed one final time after the last
            //    throttled-function call. (After the throttled-function has not been
            //    called for `delay` milliseconds, the internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the throttled-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, throttled, function.
            
            $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
              // After wrapper has stopped being called, this timeout ensures that
              // `callback` is executed at the proper times in `throttle` and `end`
              // debounce modes.
              var timeout_id,
                
                // Keep track of the last time `callback` was executed.
                last_exec = 0;
              
              // `no_trailing` defaults to falsy.
              if ( typeof no_trailing !== 'boolean' ) {
                debounce_mode = callback;
                callback = no_trailing;
                no_trailing = undefined;
              }
              
              // The `wrapper` function encapsulates all of the throttling / debouncing
              // functionality and when executed will limit the rate at which `callback`
              // is executed.
              function wrapper() {
                var that = this,
                  elapsed = +new Date() - last_exec,
                  args = arguments;
                
                // Execute `callback` and update the `last_exec` timestamp.
                function exec() {
                  last_exec = +new Date();
                  callback.apply( that, args );
                };
                
                // If `debounce_mode` is true (at_begin) this is used to clear the flag
                // to allow future `callback` executions.
                function clear() {
                  timeout_id = undefined;
                };
                
                if ( debounce_mode && !timeout_id ) {
                  // Since `wrapper` is being called for the first time and
                  // `debounce_mode` is true (at_begin), execute `callback`.
                  exec();
                }
                
                // Clear any existing timeout.
                timeout_id && clearTimeout( timeout_id );
                
                if ( debounce_mode === undefined && elapsed > delay ) {
                  // In throttle mode, if `delay` time has been exceeded, execute
                  // `callback`.
                  exec();
                  
                } else if ( no_trailing !== true ) {
                  // In trailing throttle mode, since `delay` time has not been
                  // exceeded, schedule `callback` to execute `delay` ms after most
                  // recent execution.
                  // 
                  // If `debounce_mode` is true (at_begin), schedule `clear` to execute
                  // after `delay` ms.
                  // 
                  // If `debounce_mode` is false (at end), schedule `callback` to
                  // execute after `delay` ms.
                  timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
                }
              };
              
              // Set the guid of `wrapper` function to the same of original callback, so
              // it can be removed in jQuery 1.4+ .unbind or .die by using the original
              // callback as a reference.
              if ( $.guid ) {
                wrapper.guid = callback.guid = callback.guid || $.guid++;
              }
              
              // Return the wrapper function.
              return wrapper;
            };
            
            // Method: jQuery.debounce
            // 
            // Debounce execution of a function. Debouncing, unlike throttling,
            // guarantees that a function is only executed a single time, either at the
            // very beginning of a series of calls, or at the very end. If you want to
            // simply rate-limit execution of a function, see the <jQuery.throttle>
            // method.
            // 
            // In this visualization, | is a debounced-function call and X is the actual
            // callback execution:
            // 
            // > Debounced with `at_begin` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // >                          X                                 X
            // > 
            // > Debounced with `at_begin` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X                                 X
            // 
            // Usage:
            // 
            // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', debounced );
            // > jQuery('selector').unbind( 'someevent', debounced );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
            //    unspecified, callback will only be executed `delay` milliseconds after
            //    the last debounced-function call. If at_begin is true, callback will be
            //    executed only at the first debounced-function call. (After the
            //    throttled-function has not been called for `delay` milliseconds, the
            //    internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the debounced-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, debounced, function.
            
            $.debounce = function( delay, at_begin, callback ) {
              return callback === undefined
                ? jq_throttle( delay, at_begin, false )
                : jq_throttle( delay, callback, at_begin !== false );
            };
            
          })(this);
          
          Evidence
          later
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        25. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bWHERE\b and was detected in the element starting with: "// tested with, what browsers it has been tested in, and where the unit tests", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (393 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 10254
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"10254-1268025194000"
          Last-Modified: Mon, 08 Mar 2010 05:13:14 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (10254 bytes)
          /*!
           * jQuery throttle / debounce - v1.1 - 3/7/2010
           * http://benalman.com/projects/jquery-throttle-debounce-plugin/
           * 
           * Copyright (c) 2010 "Cowboy" Ben Alman
           * Dual licensed under the MIT and GPL licenses.
           * http://benalman.com/about/license/
           */
          
          // Script: jQuery throttle / debounce: Sometimes, less is more!
          //
          // *Version: 1.1, Last updated: 3/7/2010*
          // 
          // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
          // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
          // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
          // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
          // 
          // About: License
          // 
          // Copyright (c) 2010 "Cowboy" Ben Alman,
          // Dual licensed under the MIT and GPL licenses.
          // http://benalman.com/about/license/
          // 
          // About: Examples
          // 
          // These working examples, complete with fully commented code, illustrate a few
          // ways in which this plugin can be used.
          // 
          // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
          // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
          // 
          // About: Support and Testing
          // 
          // Information about what version or versions of jQuery this plugin has been
          // tested with, what browsers it has been tested in, and where the unit tests
          // reside (so you can test it yourself).
          // 
          // jQuery Versions - none, 1.3.2, 1.4.2
          // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
          // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
          // 
          // About: Release History
          // 
          // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
          //       executed later than they should. Reworked a fair amount of internal
          //       logic as well.
          // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
          //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
          //       no_trailing throttle parameter and debounce functionality.
          // 
          // Topic: Note for non-jQuery users
          // 
          // jQuery isn't actually required for this plugin, because nothing internal
          // uses any jQuery methods or properties. jQuery is just used as a namespace
          // under which these methods can exist.
          // 
          // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
          // when this plugin is loaded, the method described below will be created in
          // the `Cowboy` namespace. Usage will be exactly the same, but instead of
          // $.method() or jQuery.method(), you'll need to use Cowboy.method().
          
          (function(window,undefined){
            '$:nomunge'; // Used by YUI compressor.
            
            // Since jQuery really isn't required for this plugin, use `jQuery` as the
            // namespace only if it already exists, otherwise use the `Cowboy` namespace,
            // creating it if necessary.
            var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
              
              // Internal method reference.
              jq_throttle;
            
            // Method: jQuery.throttle
            // 
            // Throttle execution of a function. Especially useful for rate limiting
            // execution of handlers on events like resize and scroll. If you want to
            // rate-limit execution of a function to a single time, see the
            // <jQuery.debounce> method.
            // 
            // In this visualization, | is a throttled-function call and X is the actual
            // callback execution:
            // 
            // > Throttled with `no_trailing` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X    X        X    X    X    X    X    X
            // > 
            // > Throttled with `no_trailing` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X    X    X    X    X             X    X    X    X    X
            // 
            // Usage:
            // 
            // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', throttled );
            // > jQuery('selector').unbind( 'someevent', throttled );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
            //    true, callback will only execute every `delay` milliseconds while the
            //    throttled-function is being called. If no_trailing is false or
            //    unspecified, callback will be executed one final time after the last
            //    throttled-function call. (After the throttled-function has not been
            //    called for `delay` milliseconds, the internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the throttled-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, throttled, function.
            
            $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
              // After wrapper has stopped being called, this timeout ensures that
              // `callback` is executed at the proper times in `throttle` and `end`
              // debounce modes.
              var timeout_id,
                
                // Keep track of the last time `callback` was executed.
                last_exec = 0;
              
              // `no_trailing` defaults to falsy.
              if ( typeof no_trailing !== 'boolean' ) {
                debounce_mode = callback;
                callback = no_trailing;
                no_trailing = undefined;
              }
              
              // The `wrapper` function encapsulates all of the throttling / debouncing
              // functionality and when executed will limit the rate at which `callback`
              // is executed.
              function wrapper() {
                var that = this,
                  elapsed = +new Date() - last_exec,
                  args = arguments;
                
                // Execute `callback` and update the `last_exec` timestamp.
                function exec() {
                  last_exec = +new Date();
                  callback.apply( that, args );
                };
                
                // If `debounce_mode` is true (at_begin) this is used to clear the flag
                // to allow future `callback` executions.
                function clear() {
                  timeout_id = undefined;
                };
                
                if ( debounce_mode && !timeout_id ) {
                  // Since `wrapper` is being called for the first time and
                  // `debounce_mode` is true (at_begin), execute `callback`.
                  exec();
                }
                
                // Clear any existing timeout.
                timeout_id && clearTimeout( timeout_id );
                
                if ( debounce_mode === undefined && elapsed > delay ) {
                  // In throttle mode, if `delay` time has been exceeded, execute
                  // `callback`.
                  exec();
                  
                } else if ( no_trailing !== true ) {
                  // In trailing throttle mode, since `delay` time has not been
                  // exceeded, schedule `callback` to execute `delay` ms after most
                  // recent execution.
                  // 
                  // If `debounce_mode` is true (at_begin), schedule `clear` to execute
                  // after `delay` ms.
                  // 
                  // If `debounce_mode` is false (at end), schedule `callback` to
                  // execute after `delay` ms.
                  timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
                }
              };
              
              // Set the guid of `wrapper` function to the same of original callback, so
              // it can be removed in jQuery 1.4+ .unbind or .die by using the original
              // callback as a reference.
              if ( $.guid ) {
                wrapper.guid = callback.guid = callback.guid || $.guid++;
              }
              
              // Return the wrapper function.
              return wrapper;
            };
            
            // Method: jQuery.debounce
            // 
            // Debounce execution of a function. Debouncing, unlike throttling,
            // guarantees that a function is only executed a single time, either at the
            // very beginning of a series of calls, or at the very end. If you want to
            // simply rate-limit execution of a function, see the <jQuery.throttle>
            // method.
            // 
            // In this visualization, | is a debounced-function call and X is the actual
            // callback execution:
            // 
            // > Debounced with `at_begin` specified as false or unspecified:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // >                          X                                 X
            // > 
            // > Debounced with `at_begin` specified as true:
            // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
            // > X                                 X
            // 
            // Usage:
            // 
            // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
            // > 
            // > jQuery('selector').bind( 'someevent', debounced );
            // > jQuery('selector').unbind( 'someevent', debounced );
            // 
            // This also works in jQuery 1.4+:
            // 
            // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
            // > jQuery('selector').unbind( 'someevent', callback );
            // 
            // Arguments:
            // 
            //  delay - (Number) A zero-or-greater delay in milliseconds. For event
            //    callbacks, values around 100 or 250 (or even higher) are most useful.
            //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
            //    unspecified, callback will only be executed `delay` milliseconds after
            //    the last debounced-function call. If at_begin is true, callback will be
            //    executed only at the first debounced-function call. (After the
            //    throttled-function has not been called for `delay` milliseconds, the
            //    internal counter is reset)
            //  callback - (Function) A function to be executed after delay milliseconds.
            //    The `this` context and all arguments are passed through, as-is, to
            //    `callback` when the debounced-function is executed.
            // 
            // Returns:
            // 
            //  (Function) A new, debounced, function.
            
            $.debounce = function( delay, at_begin, callback ) {
              return callback === undefined
                ? jq_throttle( delay, at_begin, false )
                : jq_throttle( delay, callback, at_begin !== false );
            };
            
          })(this);
          
          Evidence
          where
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        26. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected 2 times, the first in the element starting with: " * or promote products derived from this software without specific prior written permission.", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (419 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (449 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 6717
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"6717-1265153602000"
          Last-Modified: Tue, 02 Feb 2010 23:33:22 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (6717 bytes)
          /*
           * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
           *
           * Uses the built in easing capabilities added In jQuery 1.1
           * to offer multiple easing options
           *
           * TERMS OF USE - jQuery Easing
           * 
           * Open source under the BSD License. 
           * 
           * Copyright © 2008 George McGinley Smith
           * All rights reserved.
           * 
           * Redistribution and use in source and binary forms, with or without modification, 
           * are permitted provided that the following conditions are met:
           * 
           * Redistributions of source code must retain the above copyright notice, this list of 
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list 
           * of conditions and the following disclaimer in the documentation and/or other materials 
           * provided with the distribution.
           * 
           * Neither the name of the author nor the names of contributors may be used to endorse 
           * or promote products derived from this software without specific prior written permission.
           * 
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
           * OF THE POSSIBILITY OF SUCH DAMAGE. 
           *
          */
          
          // t: current time, b: begInnIng value, c: change In value, d: duration
          eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{}))
          
          /*
           *
           * TERMS OF USE - EASING EQUATIONS
           * 
           * Open source under the BSD License. 
           * 
           * Copyright © 2001 Robert Penner
           * All rights reserved.
           * 
           * Redistribution and use in source and binary forms, with or without modification, 
           * are permitted provided that the following conditions are met:
           * 
           * Redistributions of source code must retain the above copyright notice, this list of 
           * conditions and the following disclaimer.
           * Redistributions in binary form must reproduce the above copyright notice, this list 
           * of conditions and the following disclaimer in the documentation and/or other materials 
           * provided with the distribution.
           * 
           * Neither the name of the author nor the names of contributors may be used to endorse 
           * or promote products derived from this software without specific prior written permission.
           * 
           * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
           * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
           *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
           *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
           *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
           * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
           *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
           * OF THE POSSIBILITY OF SUCH DAMAGE. 
           *
           */
          
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        27. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected 4 times, the first in the element starting with: " from = {}, ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (418 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 28094
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"28094-1267813320000"
          Last-Modified: Fri, 05 Mar 2010 18:22:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (28094 bytes)
          /*
           * FancyBox - jQuery Plugin
           * Simple and fancy lightbox alternative
           *
           * Examples and documentation at: http://fancybox.net
           * 
           * Copyright (c) 2008 - 2010 Janis Skarnelis
           *
           * Version: 1.3.1 (05/03/2010)
           * Requires: jQuery v1.3+
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          	var tmp, loading, overlay, wrap, outer, inner, close, nav_left, nav_right,
          
          		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
          
          		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
          
          		loadingTimer, loadingFrame = 1,
          
          		start_pos, final_pos, busy = false, shadow = 20, fx = $.extend($('<div/>')[0], { prop: 0 }), titleh = 0, 
          
          		isIE6 = !$.support.opacity && !window.XMLHttpRequest,
          
          		/*
          		 * Private methods 
          		 */
          
          		fancybox_abort = function() {
          			loading.hide();
          
          			imgPreloader.onerror = imgPreloader.onload = null;
          
          			if (ajaxLoader) {
          				ajaxLoader.abort();
          			}
          
          			tmp.empty();
          		},
          
          		fancybox_error = function() {
          			$.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', {
          				'scrolling'		: 'no',
          				'padding'		: 20,
          				'transitionIn'	: 'none',
          				'transitionOut'	: 'none'
          			});
          		},
          
          		fancybox_get_viewport = function() {
          			return [ $(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ];
          		},
          
          		fancybox_get_zoom_to = function () {
          			var view	= fancybox_get_viewport(),
          				to		= {},
          
          				margin = currentOpts.margin,
          				resize = currentOpts.autoScale,
          
          				horizontal_space	= (shadow + margin) * 2,
          				vertical_space		= (shadow + margin) * 2,
          				double_padding		= (currentOpts.padding * 2),
          				
          				ratio;
          
          			if (currentOpts.width.toString().indexOf('%') > -1) {
          				to.width = ((view[0] * parseFloat(currentOpts.width)) / 100) - (shadow * 2) ;
          				resize = false;
          
          			} else {
          				to.width = currentOpts.width + double_padding;
          			}
          
          			if (currentOpts.height.toString().indexOf('%') > -1) {
          				to.height = ((view[1] * parseFloat(currentOpts.height)) / 100) - (shadow * 2);
          				resize = false;
          
          			} else {
          				to.height = currentOpts.height + double_padding;
          			}
          
          			if (resize && (to.width > (view[0] - horizontal_space) || to.height > (view[1] - vertical_space))) {
          				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
          					horizontal_space	+= double_padding;
          					vertical_space		+= double_padding;
          
          					ratio = Math.min(Math.min( view[0] - horizontal_space, currentOpts.width) / currentOpts.width, Math.min( view[1] - vertical_space, currentOpts.height) / currentOpts.height);
          
          					to.width	= Math.round(ratio * (to.width	- double_padding)) + double_padding;
          					to.height	= Math.round(ratio * (to.height	- double_padding)) + double_padding;
          
          				} else {
          					to.width	= Math.min(to.width,	(view[0] - horizontal_space));
          					to.height	= Math.min(to.height,	(view[1] - vertical_space));
          				}
          			}
          
          			to.top	= view[3] + ((view[1] - (to.height	+ (shadow * 2 ))) * 0.5);
          			to.left	= view[2] + ((view[0] - (to.width	+ (shadow * 2 ))) * 0.5);
          
          			if (currentOpts.autoScale === false) {
          				to.top	= Math.max(view[3] + margin, to.top);
          				to.left	= Math.max(view[2] + margin, to.left);
          			}
          
          			return to;
          		},
          
          		fancybox_format_title = function(title) {
          			if (title && title.length) {
          				switch (currentOpts.titlePosition) {
          					case 'inside':
          						return title;
          					case 'over':
          						return '<span id="fancybox-title-over">' + title + '</span>';
          					default:
          						return '<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">' + title + '</span><span id="fancybox-title-right"></span></span>';
          				}
          			}
          
          			return false;
          		},
          
          		fancybox_process_title = function() {
          			var title	= currentOpts.title,
          				width	= final_pos.width - (currentOpts.padding * 2),
          				titlec	= 'fancybox-title-' + currentOpts.titlePosition;
          				
          			$('#fancybox-title').remove();
          
          			titleh = 0;
          
          			if (currentOpts.titleShow === false) {
          				return;
          			}
          
          			title = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(title, currentArray, currentIndex, currentOpts) : fancybox_format_title(title);
          
          			if (!title || title === '') {
          				return;
          			}
          
          			$('<div id="fancybox-title" class="' + titlec + '" />').css({
          				'width'			: width,
          				'paddingLeft'	: currentOpts.padding,
          				'paddingRight'	: currentOpts.padding
          			}).html(title).appendTo('body');
          
          			switch (currentOpts.titlePosition) {
          				case 'inside':
          					titleh = $("#fancybox-title").outerHeight(true) - currentOpts.padding;
          					final_pos.height += titleh;
          				break;
          
          				case 'over':
          					$('#fancybox-title').css('bottom', currentOpts.padding);
          				break;
          
          				default:
          					$('#fancybox-title').css('bottom', $("#fancybox-title").outerHeight(true) * -1);
          				break;
          			}
          
          			$('#fancybox-title').appendTo( outer ).hide();
          		},
          
          		fancybox_set_navigation = function() {
          			$(document).unbind('keydown.fb').bind('keydown.fb', function(e) {
          				if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
          					e.preventDefault();
          					$.fancybox.close();
          
          				} else if (e.keyCode == 37) {
          					e.preventDefault();
          					$.fancybox.prev();
          
          				} else if (e.keyCode == 39) {
          					e.preventDefault();
          					$.fancybox.next();
          				}
          			});
          
          			if ($.fn.mousewheel) {
          				wrap.unbind('mousewheel.fb');
          
          				if (currentArray.length > 1) {
          					wrap.bind('mousewheel.fb', function(e, delta) {
          						e.preventDefault();
          
          						if (busy || delta === 0) {
          							return;
          						}
          
          						if (delta > 0) {
          							$.fancybox.prev();
          						} else {
          							$.fancybox.next();
          						}
          					});
          				}
          			}
          
          			if (!currentOpts.showNavArrows) { return; }
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
          				nav_left.show();
          			}
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
          				nav_right.show();
          			}
          		},
          
          		fancybox_preload_images = function() {
          			var href, 
          				objNext;
          				
          			if ((currentArray.length -1) > currentIndex) {
          				href = currentArray[ currentIndex + 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          
          			if (currentIndex > 0) {
          				href = currentArray[ currentIndex - 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          		},
          
          		_finish = function () {
          			inner.css('overflow', (currentOpts.scrolling == 'auto' ? (currentOpts.type == 'image' || currentOpts.type == 'iframe' || currentOpts.type == 'swf' ? 'hidden' : 'auto') : (currentOpts.scrolling == 'yes' ? 'auto' : 'visible')));
          
          			if (!$.support.opacity) {
          				inner.get(0).style.removeAttribute('filter');
          				wrap.get(0).style.removeAttribute('filter');
          			}
          
          			$('#fancybox-title').show();
          
          			if (currentOpts.hideOnContentClick)	{
          				inner.one('click', $.fancybox.close);
          			}
          			if (currentOpts.hideOnOverlayClick)	{
          				overlay.one('click', $.fancybox.close);
          			}
          
          			if (currentOpts.showCloseButton) {
          				close.show();
          			}
          
          			fancybox_set_navigation();
          
          			$(window).bind("resize.fb", $.fancybox.center);
          
          			if (currentOpts.centerOnScroll) {
          				$(window).bind("scroll.fb", $.fancybox.center);
          			} else {
          				$(window).unbind("scroll.fb");
          			}
          
          			if ($.isFunction(currentOpts.onComplete)) {
          				currentOpts.onComplete(currentArray, currentIndex, currentOpts);
          			}
          
          			busy = false;
          
          			fancybox_preload_images();
          		},
          
          		fancybox_draw = function(pos) {
          			var width	= Math.round(start_pos.width	+ (final_pos.width	- start_pos.width)	* pos),
          				height	= Math.round(start_pos.height	+ (final_pos.height	- start_pos.height)	* pos),
          
          				top		= Math.round(start_pos.top	+ (final_pos.top	- start_pos.top)	* pos),
          				left	= Math.round(start_pos.left	+ (final_pos.left	- start_pos.left)	* pos);
          
          			wrap.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px',
          				'top'		: top		+ 'px',
          				'left'		: left		+ 'px'
          			});
          
          			width	= Math.max(width - currentOpts.padding * 2, 0);
          			height	= Math.max(height - (currentOpts.padding * 2 + (titleh * pos)), 0);
          
          			inner.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px'
          			});
          
          			if (typeof final_pos.opacity !== 'undefined') {
          				wrap.css('opacity', (pos < 0.5 ? 0.5 : pos));
          			}
          		},
          
          		fancybox_get_obj_pos = function(obj) {
          			var pos		= obj.offset();
          
          			pos.top		+= parseFloat( obj.css('paddingTop') )	|| 0;
          			pos.left	+= parseFloat( obj.css('paddingLeft') )	|| 0;
          
          			pos.top		+= parseFloat( obj.css('border-top-width') )	|| 0;
          			pos.left	+= parseFloat( obj.css('border-left-width') )	|| 0;
          
          			pos.width	= obj.width();
          			pos.height	= obj.height();
          
          			return pos;
          		},
          
          		fancybox_get_zoom_from = function() {
          			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
          				from = {},
          				pos,
          				view;
          
          			if (orig && orig.length) {
          				pos = fancybox_get_obj_pos(orig);
          
          				from = {
          					width	: (pos.width	+ (currentOpts.padding * 2)),
          					height	: (pos.height	+ (currentOpts.padding * 2)),
          					top		: (pos.top		- currentOpts.padding - shadow),
          					left	: (pos.left		- currentOpts.padding - shadow)
          				};
          				
          			} else {
          				view = fancybox_get_viewport();
          
          				from = {
          					width	: 1,
          					height	: 1,
          					top		: view[3] + view[1] * 0.5,
          					left	: view[2] + view[0] * 0.5
          				};
          			}
          
          			return from;
          		},
          
          		fancybox_show = function() {
          			loading.hide();
          
          			if (wrap.is(":visible") && $.isFunction(currentOpts.onCleanup)) {
          				if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          					$.event.trigger('fancybox-cancel');
          
          					busy = false;
          					return;
          				}
          			}
          
          			currentArray	= selectedArray;
          			currentIndex	= selectedIndex;
          			currentOpts		= selectedOpts;
          
          			inner.get(0).scrollTop	= 0;
          			inner.get(0).scrollLeft	= 0;
          
          			if (currentOpts.overlayShow) {
          				if (isIE6) {
          					$('select:not(#fancybox-tmp select)').filter(function() {
          						return this.style.visibility !== 'hidden';
          					}).css({'visibility':'hidden'}).one('fancybox-cleanup', function() {
          						this.style.visibility = 'inherit';
          					});
          				}
          
          				overlay.css({
          					'background-color'	: currentOpts.overlayColor,
          					'opacity'			: currentOpts.overlayOpacity
          				}).unbind().show();
          			}
          
          			final_pos = fancybox_get_zoom_to();
          
          			fancybox_process_title();
          
          			if (wrap.is(":visible")) {
          				$( close.add( nav_left ).add( nav_right ) ).hide();
          
          				var pos = wrap.position(),
          					equal;
          
          				start_pos = {
          					top		:	pos.top ,
          					left	:	pos.left,
          					width	:	wrap.width(),
          					height	:	wrap.height()
          				};
          
          				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
          
          				inner.fadeOut(currentOpts.changeFade, function() {
          					var finish_resizing = function() {
          						inner.html( tmp.contents() ).fadeIn(currentOpts.changeFade, _finish);
          					};
          					
          					$.event.trigger('fancybox-change');
          
          					inner.empty().css('overflow', 'hidden');
          
          					if (equal) {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          						});
          						
          						finish_resizing();
          
          					} else {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          						});
          						
          						fx.prop = 0;
          
          						$(fx).animate({ prop: 1 }, {
          							 duration	: currentOpts.changeSpeed,
          							 easing		: currentOpts.easingChange,
          							 step		: fancybox_draw,
          							 complete	: finish_resizing
          						});
          					}
          				});
          
          				return;
          			}
          
          			wrap.css('opacity', 1);
          
          			if (currentOpts.transitionIn == 'elastic') {
          				start_pos = fancybox_get_zoom_from();
          
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css(start_pos).show();
          
          				if (currentOpts.opacity) {
          					final_pos.opacity = 0;
          				}
          
          				fx.prop = 0;
          
          				$(fx).animate({ prop: 1 }, {
          					 duration	: currentOpts.speedIn,
          					 easing		: currentOpts.easingIn,
          					 step		: fancybox_draw,
          					 complete	: _finish
          				});
          
          			} else {
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css( final_pos ).fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
          			}
          		},
          
          		fancybox_process_inline = function() {
          			tmp.width(	selectedOpts.width );
          			tmp.height(	selectedOpts.height );
          
          			if (selectedOpts.width	== 'auto') {
          				selectedOpts.width = tmp.width();
          			}
          			if (selectedOpts.height	== 'auto') {
          				selectedOpts.height	= tmp.height();
          			}
          
          			fancybox_show();
          		},
          		
          		fancybox_process_image = function() {
          			busy = true;
          
          			selectedOpts.width	= imgPreloader.width;
          			selectedOpts.height	= imgPreloader.height;
          
          			$("<img />").attr({
          				'id'	: 'fancybox-img',
          				'src'	: imgPreloader.src,
          				'alt'	: selectedOpts.title
          			}).appendTo( tmp );
          
          			fancybox_show();
          		},
          
          		fancybox_start = function() {
          			fancybox_abort();
          
          			var obj	= selectedArray[ selectedIndex ],
          				href, 
          				type, 
          				title,
          				str,
          				emb,
          				selector,
          				data;
          
          			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
          			title = obj.title || $(obj).title || selectedOpts.title || '';
          			
          			if (obj.nodeName && !selectedOpts.orig) {
          				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
          			}
          
          			if (title === '' && selectedOpts.orig) {
          				title = selectedOpts.orig.attr('alt');
          			}
          
          			if (obj.nodeName && (/^(?:javascript|#)/i).test(obj.href)) {
          				href = selectedOpts.href || null;
          			} else {
          				href = selectedOpts.href || obj.href || null;
          			}
          
          			if (selectedOpts.type) {
          				type = selectedOpts.type;
          
          				if (!href) {
          					href = selectedOpts.content;
          				}
          				
          			} else if (selectedOpts.content) {
          				type	= 'html';
          
          			} else if (href) {
          				if (href.match(imgRegExp)) {
          					type = 'image';
          
          				} else if (href.match(swfRegExp)) {
          					type = 'swf';
          
          				} else if ($(obj).hasClass("iframe")) {
          					type = 'iframe';
          
          				} else if (href.match(/#/)) {
          					obj = href.substr(href.indexOf("#"));
          
          					type = $(obj).length > 0 ? 'inline' : 'ajax';
          				} else {
          					type = 'ajax';
          				}
          			} else {
          				type = 'inline';
          			}
          
          			selectedOpts.type	= type;
          			selectedOpts.href	= href;
          			selectedOpts.title	= title;
          
          			if (selectedOpts.autoDimensions && selectedOpts.type !== 'iframe' && selectedOpts.type !== 'swf') {
          				selectedOpts.width		= 'auto';
          				selectedOpts.height		= 'auto';
          			}
          
          			if (selectedOpts.modal) {
          				selectedOpts.overlayShow		= true;
          				selectedOpts.hideOnOverlayClick	= false;
          				selectedOpts.hideOnContentClick	= false;
          				selectedOpts.enableEscapeButton	= false;
          				selectedOpts.showCloseButton	= false;
          			}
          
          			if ($.isFunction(selectedOpts.onStart)) {
          				if (selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts) === false) {
          					busy = false;
          					return;
          				}
          			}
          
          			tmp.css('padding', (shadow + selectedOpts.padding + selectedOpts.margin));
          
          			$('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
          				$(this).replaceWith(inner.children());
          			});
          
          			switch (type) {
          				case 'html' :
          					tmp.html( selectedOpts.content );
          					fancybox_process_inline();
          				break;
          
          				case 'inline' :
          					$('<div class="fancybox-inline-tmp" />').hide().insertBefore( $(obj) ).bind('fancybox-cleanup', function() {
          						$(this).replaceWith(inner.children());
          					}).bind('fancybox-cancel', function() {
          						$(this).replaceWith(tmp.children());
          					});
          
          					$(obj).appendTo(tmp);
          
          					fancybox_process_inline();
          				break;
          
          				case 'image':
          					busy = false;
          
          					$.fancybox.showActivity();
          
          					imgPreloader = new Image();
          
          					imgPreloader.onerror = function() {
          						fancybox_error();
          					};
          
          					imgPreloader.onload = function() {
          						imgPreloader.onerror = null;
          						imgPreloader.onload = null;
          						fancybox_process_image();
          					};
          
          					imgPreloader.src = href;
          		
          				break;
          
          				case 'swf':
          					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
          					emb = '';
          					
          					$.each(selectedOpts.swf, function(name, val) {
          						str += '<param name="' + name + '" value="' + val + '"></param>';
          						emb += ' ' + name + '="' + val + '"';
          					});
          
          					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
          
          					tmp.html(str);
          
          					fancybox_process_inline();
          				break;
          
          				case 'ajax':
          					selector	= href.split('#', 2);
          					data		= selectedOpts.ajax.data || {};
          
          					if (selector.length > 1) {
          						href = selector[0];
          
          						if (typeof data == "string") {
          							data += '&selector=' + selector[1];
          						} else {
          							data.selector = selector[1];
          						}
          					}
          
          					busy = false;
          					$.fancybox.showActivity();
          
          					ajaxLoader = $.ajax($.extend(selectedOpts.ajax, {
          						url		: href,
          						data	: data,
          						error	: fancybox_error,
          						success : function(data, textStatus, XMLHttpRequest) {
          							if (ajaxLoader.status == 200) {
          								tmp.html( data );
          								fancybox_process_inline();
          							}
          						}
          					}));
          
          				break;
          
          				case 'iframe' :
          					$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" scrolling="' + selectedOpts.scrolling + '" src="' + selectedOpts.href + '"></iframe>').appendTo(tmp);
          					fancybox_show();
          				break;
          			}
          		},
          
          		fancybox_animate_loading = function() {
          			if (!loading.is(':visible')){
          				clearInterval(loadingTimer);
          				return;
          			}
          
          			$('div', loading).css('top', (loadingFrame * -40) + 'px');
          
          			loadingFrame = (loadingFrame + 1) % 12;
          		},
          
          		fancybox_init = function() {
          			if ($("#fancybox-wrap").length) {
          				return;
          			}
          
          			$('body').append(
          				tmp			= $('<div id="fancybox-tmp"></div>'),
          				loading		= $('<div id="fancybox-loading"><div></div></div>'),
          				overlay		= $('<div id="fancybox-overlay"></div>'),
          				wrap		= $('<div id="fancybox-wrap"></div>')
          			);
          
          			if (!$.support.opacity) {
          				wrap.addClass('fancybox-ie');
          				loading.addClass('fancybox-ie');
          			}
          
          			outer = $('<div id="fancybox-outer"></div>')
          				.append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>')
          				.appendTo( wrap );
          
          			outer.append(
          				inner		= $('<div id="fancybox-inner"></div>'),
          				close		= $('<a id="fancybox-close"></a>'),
          
          				nav_left	= $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
          				nav_right	= $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
          			);
          
          			close.click($.fancybox.close);
          			loading.click($.fancybox.cancel);
          
          			nav_left.click(function(e) {
          				e.preventDefault();
          				$.fancybox.prev();
          			});
          
          			nav_right.click(function(e) {
          				e.preventDefault();
          				$.fancybox.next();
          			});
          
          			if (isIE6) {
          				overlay.get(0).style.setExpression('height',	"document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");
          				loading.get(0).style.setExpression('top',		"(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");
          
          				outer.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>');
          			}
          		};
          
          	/*
          	 * Public methods 
          	 */
          
          	$.fn.fancybox = function(options) {
          		$(this)
          			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
          			.unbind('click.fb').bind('click.fb', function(e) {
          				e.preventDefault();
          
          				if (busy) {
          					return;
          				}
          
          				busy = true;
          
          				$(this).blur();
          
          				selectedArray	= [];
          				selectedIndex	= 0;
          
          				var rel = $(this).attr('rel') || '';
          
          				if (!rel || rel == '' || rel === 'nofollow') {
          					selectedArray.push(this);
          
          				} else {
          					selectedArray	= $("a[rel=" + rel + "], area[rel=" + rel + "]");
          					selectedIndex	= selectedArray.index( this );
          				}
          
          				fancybox_start();
          
          				return false;
          			});
          
          		return this;
          	};
          
          	$.fancybox = function(obj) {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		var opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
          
          		selectedArray	= [];
          		selectedIndex	= opts.index || 0;
          
          		if ($.isArray(obj)) {
          			for (var i = 0, j = obj.length; i < j; i++) {
          				if (typeof obj[i] == 'object') {
          					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
          				} else {
          					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
          				}
          			}
          
          			selectedArray = jQuery.merge(selectedArray, obj);
          
          		} else {
          			if (typeof obj == 'object') {
          				$(obj).data('fancybox', $.extend({}, opts, obj));
          			} else {
          				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
          			}
          
          			selectedArray.push(obj);
          		}
          
          		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
          			selectedIndex = 0;
          		}
          
          		fancybox_start();
          	};
          
          	$.fancybox.showActivity = function() {
          		clearInterval(loadingTimer);
          
          		loading.show();
          		loadingTimer = setInterval(fancybox_animate_loading, 66);
          	};
          
          	$.fancybox.hideActivity = function() {
          		loading.hide();
          	};
          
          	$.fancybox.next = function() {
          		return $.fancybox.pos( currentIndex + 1);
          	};
          	
          	$.fancybox.prev = function() {
          		return $.fancybox.pos( currentIndex - 1);
          	};
          
          	$.fancybox.pos = function(pos) {
          		if (busy) {
          			return;
          		}
          
          		pos = parseInt(pos, 10);
          
          		if (pos > -1 && currentArray.length > pos) {
          			selectedIndex = pos;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos < 0) {
          			selectedIndex = currentArray.length - 1;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos >= currentArray.length) {
          			selectedIndex = 0;
          			fancybox_start();
          		}
          
          		return;
          	};
          
          	$.fancybox.cancel = function() {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		$.event.trigger('fancybox-cancel');
          
          		fancybox_abort();
          
          		if (selectedOpts && $.isFunction(selectedOpts.onCancel)) {
          			selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
          		}
          
          		busy = false;
          	};
          
          	// Note: within an iframe use - parent.$.fancybox.close();
          	$.fancybox.close = function() {
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		if (currentOpts && $.isFunction(currentOpts.onCleanup)) {
          			if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          				busy = false;
          				return;
          			}
          		}
          
          		fancybox_abort();
          
          		$(close.add( nav_left ).add( nav_right )).hide();
          
          		$('#fancybox-title').remove();
          
          		wrap.add(inner).add(overlay).unbind();
          
          		$(window).unbind("resize.fb scroll.fb");
          		$(document).unbind('keydown.fb');
          
          		function _cleanup() {
          			overlay.fadeOut('fast');
          
          			wrap.hide();
          
          			$.event.trigger('fancybox-cleanup');
          
          			inner.empty();
          
          			if ($.isFunction(currentOpts.onClosed)) {
          				currentOpts.onClosed(currentArray, currentIndex, currentOpts);
          			}
          
          			currentArray	= selectedOpts	= [];
          			currentIndex	= selectedIndex	= 0;
          			currentOpts		= selectedOpts	= {};
          
          			busy = false;
          		}
          
          		inner.css('overflow', 'hidden');
          
          		if (currentOpts.transitionOut == 'elastic') {
          			start_pos = fancybox_get_zoom_from();
          
          			var pos = wrap.position();
          
          			final_pos = {
          				top		:	pos.top ,
          				left	:	pos.left,
          				width	:	wrap.width(),
          				height	:	wrap.height()
          			};
          
          			if (currentOpts.opacity) {
          				final_pos.opacity = 1;
          			}
          
          			fx.prop = 1;
          
          			$(fx).animate({ prop: 0 }, {
          				 duration	: currentOpts.speedOut,
          				 easing		: currentOpts.easingOut,
          				 step		: fancybox_draw,
          				 complete	: _cleanup
          			});
          
          		} else {
          			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
          		}
          	};
          
          	$.fancybox.resize = function() {
          		var c, h;
          		
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		c = inner.wrapInner("<div style='overflow:auto'></div>").children();
          		h = c.height();
          
          		wrap.css({height:	h + (currentOpts.padding * 2) + titleh});
          		inner.css({height:	h});
          
          		c.replaceWith(c.children());
          
          		$.fancybox.center();
          	};
          
          	$.fancybox.center = function() {
          		busy = true;
          
          		var view	= fancybox_get_viewport(),
          			margin	= currentOpts.margin,
          			to		= {};
          
          		to.top	= view[3] + ((view[1] - ((wrap.height() - titleh) + (shadow * 2 ))) * 0.5);
          		to.left	= view[2] + ((view[0] - (wrap.width() + (shadow * 2 ))) * 0.5);
          
          		to.top	= Math.max(view[3] + margin, to.top);
          		to.left	= Math.max(view[2] + margin, to.left);
          
          		wrap.css(to);
          
          		busy = false;
          	};
          
          	$.fn.fancybox.defaults = {
          		padding				:	10,
          		margin				:	20,
          		opacity				:	false,
          		modal				:	false,
          		cyclic				:	false,
          		scrolling			:	'auto',	// 'auto', 'yes' or 'no'
          
          		width				:	560,
          		height				:	340,
          
          		autoScale			:	true,
          		autoDimensions		:	true,
          		centerOnScroll		:	false,
          
          		ajax				:	{},
          		swf					:	{ wmode: 'transparent' },
          
          		hideOnOverlayClick	:	true,
          		hideOnContentClick	:	false,
          
          		overlayShow			:	true,
          		overlayOpacity		:	0.3,
          		overlayColor		:	'#666',
          
          		titleShow			:	true,
          		titlePosition		:	'outside',	// 'outside', 'inside' or 'over'
          		titleFormat			:	null,
          
          		transitionIn		:	'fade',	// 'elastic', 'fade' or 'none'
          		transitionOut		:	'fade',	// 'elastic', 'fade' or 'none'
          
          		speedIn				:	300,
          		speedOut			:	300,
          
          		changeSpeed			:	300,
          		changeFade			:	'fast',
          
          		easingIn			:	'swing',
          		easingOut			:	'swing',
          
          		showCloseButton		:	true,
          		showNavArrows		:	true,
          		enableEscapeButton	:	true,
          
          		onStart				:	null,
          		onCancel			:	null,
          		onComplete			:	null,
          		onCleanup			:	null,
          		onClosed			:	null
          	};
          
          	$(document).ready(function() {
          		fancybox_init();
          	});
          
          })(jQuery);
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        28. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bLATER\b and was detected in the element starting with: " $.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', { ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (418 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 28094
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"28094-1267813320000"
          Last-Modified: Fri, 05 Mar 2010 18:22:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (28094 bytes)
          /*
           * FancyBox - jQuery Plugin
           * Simple and fancy lightbox alternative
           *
           * Examples and documentation at: http://fancybox.net
           * 
           * Copyright (c) 2008 - 2010 Janis Skarnelis
           *
           * Version: 1.3.1 (05/03/2010)
           * Requires: jQuery v1.3+
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          	var tmp, loading, overlay, wrap, outer, inner, close, nav_left, nav_right,
          
          		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
          
          		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
          
          		loadingTimer, loadingFrame = 1,
          
          		start_pos, final_pos, busy = false, shadow = 20, fx = $.extend($('<div/>')[0], { prop: 0 }), titleh = 0, 
          
          		isIE6 = !$.support.opacity && !window.XMLHttpRequest,
          
          		/*
          		 * Private methods 
          		 */
          
          		fancybox_abort = function() {
          			loading.hide();
          
          			imgPreloader.onerror = imgPreloader.onload = null;
          
          			if (ajaxLoader) {
          				ajaxLoader.abort();
          			}
          
          			tmp.empty();
          		},
          
          		fancybox_error = function() {
          			$.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', {
          				'scrolling'		: 'no',
          				'padding'		: 20,
          				'transitionIn'	: 'none',
          				'transitionOut'	: 'none'
          			});
          		},
          
          		fancybox_get_viewport = function() {
          			return [ $(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ];
          		},
          
          		fancybox_get_zoom_to = function () {
          			var view	= fancybox_get_viewport(),
          				to		= {},
          
          				margin = currentOpts.margin,
          				resize = currentOpts.autoScale,
          
          				horizontal_space	= (shadow + margin) * 2,
          				vertical_space		= (shadow + margin) * 2,
          				double_padding		= (currentOpts.padding * 2),
          				
          				ratio;
          
          			if (currentOpts.width.toString().indexOf('%') > -1) {
          				to.width = ((view[0] * parseFloat(currentOpts.width)) / 100) - (shadow * 2) ;
          				resize = false;
          
          			} else {
          				to.width = currentOpts.width + double_padding;
          			}
          
          			if (currentOpts.height.toString().indexOf('%') > -1) {
          				to.height = ((view[1] * parseFloat(currentOpts.height)) / 100) - (shadow * 2);
          				resize = false;
          
          			} else {
          				to.height = currentOpts.height + double_padding;
          			}
          
          			if (resize && (to.width > (view[0] - horizontal_space) || to.height > (view[1] - vertical_space))) {
          				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
          					horizontal_space	+= double_padding;
          					vertical_space		+= double_padding;
          
          					ratio = Math.min(Math.min( view[0] - horizontal_space, currentOpts.width) / currentOpts.width, Math.min( view[1] - vertical_space, currentOpts.height) / currentOpts.height);
          
          					to.width	= Math.round(ratio * (to.width	- double_padding)) + double_padding;
          					to.height	= Math.round(ratio * (to.height	- double_padding)) + double_padding;
          
          				} else {
          					to.width	= Math.min(to.width,	(view[0] - horizontal_space));
          					to.height	= Math.min(to.height,	(view[1] - vertical_space));
          				}
          			}
          
          			to.top	= view[3] + ((view[1] - (to.height	+ (shadow * 2 ))) * 0.5);
          			to.left	= view[2] + ((view[0] - (to.width	+ (shadow * 2 ))) * 0.5);
          
          			if (currentOpts.autoScale === false) {
          				to.top	= Math.max(view[3] + margin, to.top);
          				to.left	= Math.max(view[2] + margin, to.left);
          			}
          
          			return to;
          		},
          
          		fancybox_format_title = function(title) {
          			if (title && title.length) {
          				switch (currentOpts.titlePosition) {
          					case 'inside':
          						return title;
          					case 'over':
          						return '<span id="fancybox-title-over">' + title + '</span>';
          					default:
          						return '<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">' + title + '</span><span id="fancybox-title-right"></span></span>';
          				}
          			}
          
          			return false;
          		},
          
          		fancybox_process_title = function() {
          			var title	= currentOpts.title,
          				width	= final_pos.width - (currentOpts.padding * 2),
          				titlec	= 'fancybox-title-' + currentOpts.titlePosition;
          				
          			$('#fancybox-title').remove();
          
          			titleh = 0;
          
          			if (currentOpts.titleShow === false) {
          				return;
          			}
          
          			title = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(title, currentArray, currentIndex, currentOpts) : fancybox_format_title(title);
          
          			if (!title || title === '') {
          				return;
          			}
          
          			$('<div id="fancybox-title" class="' + titlec + '" />').css({
          				'width'			: width,
          				'paddingLeft'	: currentOpts.padding,
          				'paddingRight'	: currentOpts.padding
          			}).html(title).appendTo('body');
          
          			switch (currentOpts.titlePosition) {
          				case 'inside':
          					titleh = $("#fancybox-title").outerHeight(true) - currentOpts.padding;
          					final_pos.height += titleh;
          				break;
          
          				case 'over':
          					$('#fancybox-title').css('bottom', currentOpts.padding);
          				break;
          
          				default:
          					$('#fancybox-title').css('bottom', $("#fancybox-title").outerHeight(true) * -1);
          				break;
          			}
          
          			$('#fancybox-title').appendTo( outer ).hide();
          		},
          
          		fancybox_set_navigation = function() {
          			$(document).unbind('keydown.fb').bind('keydown.fb', function(e) {
          				if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
          					e.preventDefault();
          					$.fancybox.close();
          
          				} else if (e.keyCode == 37) {
          					e.preventDefault();
          					$.fancybox.prev();
          
          				} else if (e.keyCode == 39) {
          					e.preventDefault();
          					$.fancybox.next();
          				}
          			});
          
          			if ($.fn.mousewheel) {
          				wrap.unbind('mousewheel.fb');
          
          				if (currentArray.length > 1) {
          					wrap.bind('mousewheel.fb', function(e, delta) {
          						e.preventDefault();
          
          						if (busy || delta === 0) {
          							return;
          						}
          
          						if (delta > 0) {
          							$.fancybox.prev();
          						} else {
          							$.fancybox.next();
          						}
          					});
          				}
          			}
          
          			if (!currentOpts.showNavArrows) { return; }
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
          				nav_left.show();
          			}
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
          				nav_right.show();
          			}
          		},
          
          		fancybox_preload_images = function() {
          			var href, 
          				objNext;
          				
          			if ((currentArray.length -1) > currentIndex) {
          				href = currentArray[ currentIndex + 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          
          			if (currentIndex > 0) {
          				href = currentArray[ currentIndex - 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          		},
          
          		_finish = function () {
          			inner.css('overflow', (currentOpts.scrolling == 'auto' ? (currentOpts.type == 'image' || currentOpts.type == 'iframe' || currentOpts.type == 'swf' ? 'hidden' : 'auto') : (currentOpts.scrolling == 'yes' ? 'auto' : 'visible')));
          
          			if (!$.support.opacity) {
          				inner.get(0).style.removeAttribute('filter');
          				wrap.get(0).style.removeAttribute('filter');
          			}
          
          			$('#fancybox-title').show();
          
          			if (currentOpts.hideOnContentClick)	{
          				inner.one('click', $.fancybox.close);
          			}
          			if (currentOpts.hideOnOverlayClick)	{
          				overlay.one('click', $.fancybox.close);
          			}
          
          			if (currentOpts.showCloseButton) {
          				close.show();
          			}
          
          			fancybox_set_navigation();
          
          			$(window).bind("resize.fb", $.fancybox.center);
          
          			if (currentOpts.centerOnScroll) {
          				$(window).bind("scroll.fb", $.fancybox.center);
          			} else {
          				$(window).unbind("scroll.fb");
          			}
          
          			if ($.isFunction(currentOpts.onComplete)) {
          				currentOpts.onComplete(currentArray, currentIndex, currentOpts);
          			}
          
          			busy = false;
          
          			fancybox_preload_images();
          		},
          
          		fancybox_draw = function(pos) {
          			var width	= Math.round(start_pos.width	+ (final_pos.width	- start_pos.width)	* pos),
          				height	= Math.round(start_pos.height	+ (final_pos.height	- start_pos.height)	* pos),
          
          				top		= Math.round(start_pos.top	+ (final_pos.top	- start_pos.top)	* pos),
          				left	= Math.round(start_pos.left	+ (final_pos.left	- start_pos.left)	* pos);
          
          			wrap.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px',
          				'top'		: top		+ 'px',
          				'left'		: left		+ 'px'
          			});
          
          			width	= Math.max(width - currentOpts.padding * 2, 0);
          			height	= Math.max(height - (currentOpts.padding * 2 + (titleh * pos)), 0);
          
          			inner.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px'
          			});
          
          			if (typeof final_pos.opacity !== 'undefined') {
          				wrap.css('opacity', (pos < 0.5 ? 0.5 : pos));
          			}
          		},
          
          		fancybox_get_obj_pos = function(obj) {
          			var pos		= obj.offset();
          
          			pos.top		+= parseFloat( obj.css('paddingTop') )	|| 0;
          			pos.left	+= parseFloat( obj.css('paddingLeft') )	|| 0;
          
          			pos.top		+= parseFloat( obj.css('border-top-width') )	|| 0;
          			pos.left	+= parseFloat( obj.css('border-left-width') )	|| 0;
          
          			pos.width	= obj.width();
          			pos.height	= obj.height();
          
          			return pos;
          		},
          
          		fancybox_get_zoom_from = function() {
          			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
          				from = {},
          				pos,
          				view;
          
          			if (orig && orig.length) {
          				pos = fancybox_get_obj_pos(orig);
          
          				from = {
          					width	: (pos.width	+ (currentOpts.padding * 2)),
          					height	: (pos.height	+ (currentOpts.padding * 2)),
          					top		: (pos.top		- currentOpts.padding - shadow),
          					left	: (pos.left		- currentOpts.padding - shadow)
          				};
          				
          			} else {
          				view = fancybox_get_viewport();
          
          				from = {
          					width	: 1,
          					height	: 1,
          					top		: view[3] + view[1] * 0.5,
          					left	: view[2] + view[0] * 0.5
          				};
          			}
          
          			return from;
          		},
          
          		fancybox_show = function() {
          			loading.hide();
          
          			if (wrap.is(":visible") && $.isFunction(currentOpts.onCleanup)) {
          				if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          					$.event.trigger('fancybox-cancel');
          
          					busy = false;
          					return;
          				}
          			}
          
          			currentArray	= selectedArray;
          			currentIndex	= selectedIndex;
          			currentOpts		= selectedOpts;
          
          			inner.get(0).scrollTop	= 0;
          			inner.get(0).scrollLeft	= 0;
          
          			if (currentOpts.overlayShow) {
          				if (isIE6) {
          					$('select:not(#fancybox-tmp select)').filter(function() {
          						return this.style.visibility !== 'hidden';
          					}).css({'visibility':'hidden'}).one('fancybox-cleanup', function() {
          						this.style.visibility = 'inherit';
          					});
          				}
          
          				overlay.css({
          					'background-color'	: currentOpts.overlayColor,
          					'opacity'			: currentOpts.overlayOpacity
          				}).unbind().show();
          			}
          
          			final_pos = fancybox_get_zoom_to();
          
          			fancybox_process_title();
          
          			if (wrap.is(":visible")) {
          				$( close.add( nav_left ).add( nav_right ) ).hide();
          
          				var pos = wrap.position(),
          					equal;
          
          				start_pos = {
          					top		:	pos.top ,
          					left	:	pos.left,
          					width	:	wrap.width(),
          					height	:	wrap.height()
          				};
          
          				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
          
          				inner.fadeOut(currentOpts.changeFade, function() {
          					var finish_resizing = function() {
          						inner.html( tmp.contents() ).fadeIn(currentOpts.changeFade, _finish);
          					};
          					
          					$.event.trigger('fancybox-change');
          
          					inner.empty().css('overflow', 'hidden');
          
          					if (equal) {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          						});
          						
          						finish_resizing();
          
          					} else {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          						});
          						
          						fx.prop = 0;
          
          						$(fx).animate({ prop: 1 }, {
          							 duration	: currentOpts.changeSpeed,
          							 easing		: currentOpts.easingChange,
          							 step		: fancybox_draw,
          							 complete	: finish_resizing
          						});
          					}
          				});
          
          				return;
          			}
          
          			wrap.css('opacity', 1);
          
          			if (currentOpts.transitionIn == 'elastic') {
          				start_pos = fancybox_get_zoom_from();
          
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css(start_pos).show();
          
          				if (currentOpts.opacity) {
          					final_pos.opacity = 0;
          				}
          
          				fx.prop = 0;
          
          				$(fx).animate({ prop: 1 }, {
          					 duration	: currentOpts.speedIn,
          					 easing		: currentOpts.easingIn,
          					 step		: fancybox_draw,
          					 complete	: _finish
          				});
          
          			} else {
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css( final_pos ).fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
          			}
          		},
          
          		fancybox_process_inline = function() {
          			tmp.width(	selectedOpts.width );
          			tmp.height(	selectedOpts.height );
          
          			if (selectedOpts.width	== 'auto') {
          				selectedOpts.width = tmp.width();
          			}
          			if (selectedOpts.height	== 'auto') {
          				selectedOpts.height	= tmp.height();
          			}
          
          			fancybox_show();
          		},
          		
          		fancybox_process_image = function() {
          			busy = true;
          
          			selectedOpts.width	= imgPreloader.width;
          			selectedOpts.height	= imgPreloader.height;
          
          			$("<img />").attr({
          				'id'	: 'fancybox-img',
          				'src'	: imgPreloader.src,
          				'alt'	: selectedOpts.title
          			}).appendTo( tmp );
          
          			fancybox_show();
          		},
          
          		fancybox_start = function() {
          			fancybox_abort();
          
          			var obj	= selectedArray[ selectedIndex ],
          				href, 
          				type, 
          				title,
          				str,
          				emb,
          				selector,
          				data;
          
          			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
          			title = obj.title || $(obj).title || selectedOpts.title || '';
          			
          			if (obj.nodeName && !selectedOpts.orig) {
          				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
          			}
          
          			if (title === '' && selectedOpts.orig) {
          				title = selectedOpts.orig.attr('alt');
          			}
          
          			if (obj.nodeName && (/^(?:javascript|#)/i).test(obj.href)) {
          				href = selectedOpts.href || null;
          			} else {
          				href = selectedOpts.href || obj.href || null;
          			}
          
          			if (selectedOpts.type) {
          				type = selectedOpts.type;
          
          				if (!href) {
          					href = selectedOpts.content;
          				}
          				
          			} else if (selectedOpts.content) {
          				type	= 'html';
          
          			} else if (href) {
          				if (href.match(imgRegExp)) {
          					type = 'image';
          
          				} else if (href.match(swfRegExp)) {
          					type = 'swf';
          
          				} else if ($(obj).hasClass("iframe")) {
          					type = 'iframe';
          
          				} else if (href.match(/#/)) {
          					obj = href.substr(href.indexOf("#"));
          
          					type = $(obj).length > 0 ? 'inline' : 'ajax';
          				} else {
          					type = 'ajax';
          				}
          			} else {
          				type = 'inline';
          			}
          
          			selectedOpts.type	= type;
          			selectedOpts.href	= href;
          			selectedOpts.title	= title;
          
          			if (selectedOpts.autoDimensions && selectedOpts.type !== 'iframe' && selectedOpts.type !== 'swf') {
          				selectedOpts.width		= 'auto';
          				selectedOpts.height		= 'auto';
          			}
          
          			if (selectedOpts.modal) {
          				selectedOpts.overlayShow		= true;
          				selectedOpts.hideOnOverlayClick	= false;
          				selectedOpts.hideOnContentClick	= false;
          				selectedOpts.enableEscapeButton	= false;
          				selectedOpts.showCloseButton	= false;
          			}
          
          			if ($.isFunction(selectedOpts.onStart)) {
          				if (selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts) === false) {
          					busy = false;
          					return;
          				}
          			}
          
          			tmp.css('padding', (shadow + selectedOpts.padding + selectedOpts.margin));
          
          			$('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
          				$(this).replaceWith(inner.children());
          			});
          
          			switch (type) {
          				case 'html' :
          					tmp.html( selectedOpts.content );
          					fancybox_process_inline();
          				break;
          
          				case 'inline' :
          					$('<div class="fancybox-inline-tmp" />').hide().insertBefore( $(obj) ).bind('fancybox-cleanup', function() {
          						$(this).replaceWith(inner.children());
          					}).bind('fancybox-cancel', function() {
          						$(this).replaceWith(tmp.children());
          					});
          
          					$(obj).appendTo(tmp);
          
          					fancybox_process_inline();
          				break;
          
          				case 'image':
          					busy = false;
          
          					$.fancybox.showActivity();
          
          					imgPreloader = new Image();
          
          					imgPreloader.onerror = function() {
          						fancybox_error();
          					};
          
          					imgPreloader.onload = function() {
          						imgPreloader.onerror = null;
          						imgPreloader.onload = null;
          						fancybox_process_image();
          					};
          
          					imgPreloader.src = href;
          		
          				break;
          
          				case 'swf':
          					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
          					emb = '';
          					
          					$.each(selectedOpts.swf, function(name, val) {
          						str += '<param name="' + name + '" value="' + val + '"></param>';
          						emb += ' ' + name + '="' + val + '"';
          					});
          
          					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
          
          					tmp.html(str);
          
          					fancybox_process_inline();
          				break;
          
          				case 'ajax':
          					selector	= href.split('#', 2);
          					data		= selectedOpts.ajax.data || {};
          
          					if (selector.length > 1) {
          						href = selector[0];
          
          						if (typeof data == "string") {
          							data += '&selector=' + selector[1];
          						} else {
          							data.selector = selector[1];
          						}
          					}
          
          					busy = false;
          					$.fancybox.showActivity();
          
          					ajaxLoader = $.ajax($.extend(selectedOpts.ajax, {
          						url		: href,
          						data	: data,
          						error	: fancybox_error,
          						success : function(data, textStatus, XMLHttpRequest) {
          							if (ajaxLoader.status == 200) {
          								tmp.html( data );
          								fancybox_process_inline();
          							}
          						}
          					}));
          
          				break;
          
          				case 'iframe' :
          					$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" scrolling="' + selectedOpts.scrolling + '" src="' + selectedOpts.href + '"></iframe>').appendTo(tmp);
          					fancybox_show();
          				break;
          			}
          		},
          
          		fancybox_animate_loading = function() {
          			if (!loading.is(':visible')){
          				clearInterval(loadingTimer);
          				return;
          			}
          
          			$('div', loading).css('top', (loadingFrame * -40) + 'px');
          
          			loadingFrame = (loadingFrame + 1) % 12;
          		},
          
          		fancybox_init = function() {
          			if ($("#fancybox-wrap").length) {
          				return;
          			}
          
          			$('body').append(
          				tmp			= $('<div id="fancybox-tmp"></div>'),
          				loading		= $('<div id="fancybox-loading"><div></div></div>'),
          				overlay		= $('<div id="fancybox-overlay"></div>'),
          				wrap		= $('<div id="fancybox-wrap"></div>')
          			);
          
          			if (!$.support.opacity) {
          				wrap.addClass('fancybox-ie');
          				loading.addClass('fancybox-ie');
          			}
          
          			outer = $('<div id="fancybox-outer"></div>')
          				.append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>')
          				.appendTo( wrap );
          
          			outer.append(
          				inner		= $('<div id="fancybox-inner"></div>'),
          				close		= $('<a id="fancybox-close"></a>'),
          
          				nav_left	= $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
          				nav_right	= $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
          			);
          
          			close.click($.fancybox.close);
          			loading.click($.fancybox.cancel);
          
          			nav_left.click(function(e) {
          				e.preventDefault();
          				$.fancybox.prev();
          			});
          
          			nav_right.click(function(e) {
          				e.preventDefault();
          				$.fancybox.next();
          			});
          
          			if (isIE6) {
          				overlay.get(0).style.setExpression('height',	"document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");
          				loading.get(0).style.setExpression('top',		"(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");
          
          				outer.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>');
          			}
          		};
          
          	/*
          	 * Public methods 
          	 */
          
          	$.fn.fancybox = function(options) {
          		$(this)
          			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
          			.unbind('click.fb').bind('click.fb', function(e) {
          				e.preventDefault();
          
          				if (busy) {
          					return;
          				}
          
          				busy = true;
          
          				$(this).blur();
          
          				selectedArray	= [];
          				selectedIndex	= 0;
          
          				var rel = $(this).attr('rel') || '';
          
          				if (!rel || rel == '' || rel === 'nofollow') {
          					selectedArray.push(this);
          
          				} else {
          					selectedArray	= $("a[rel=" + rel + "], area[rel=" + rel + "]");
          					selectedIndex	= selectedArray.index( this );
          				}
          
          				fancybox_start();
          
          				return false;
          			});
          
          		return this;
          	};
          
          	$.fancybox = function(obj) {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		var opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
          
          		selectedArray	= [];
          		selectedIndex	= opts.index || 0;
          
          		if ($.isArray(obj)) {
          			for (var i = 0, j = obj.length; i < j; i++) {
          				if (typeof obj[i] == 'object') {
          					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
          				} else {
          					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
          				}
          			}
          
          			selectedArray = jQuery.merge(selectedArray, obj);
          
          		} else {
          			if (typeof obj == 'object') {
          				$(obj).data('fancybox', $.extend({}, opts, obj));
          			} else {
          				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
          			}
          
          			selectedArray.push(obj);
          		}
          
          		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
          			selectedIndex = 0;
          		}
          
          		fancybox_start();
          	};
          
          	$.fancybox.showActivity = function() {
          		clearInterval(loadingTimer);
          
          		loading.show();
          		loadingTimer = setInterval(fancybox_animate_loading, 66);
          	};
          
          	$.fancybox.hideActivity = function() {
          		loading.hide();
          	};
          
          	$.fancybox.next = function() {
          		return $.fancybox.pos( currentIndex + 1);
          	};
          	
          	$.fancybox.prev = function() {
          		return $.fancybox.pos( currentIndex - 1);
          	};
          
          	$.fancybox.pos = function(pos) {
          		if (busy) {
          			return;
          		}
          
          		pos = parseInt(pos, 10);
          
          		if (pos > -1 && currentArray.length > pos) {
          			selectedIndex = pos;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos < 0) {
          			selectedIndex = currentArray.length - 1;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos >= currentArray.length) {
          			selectedIndex = 0;
          			fancybox_start();
          		}
          
          		return;
          	};
          
          	$.fancybox.cancel = function() {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		$.event.trigger('fancybox-cancel');
          
          		fancybox_abort();
          
          		if (selectedOpts && $.isFunction(selectedOpts.onCancel)) {
          			selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
          		}
          
          		busy = false;
          	};
          
          	// Note: within an iframe use - parent.$.fancybox.close();
          	$.fancybox.close = function() {
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		if (currentOpts && $.isFunction(currentOpts.onCleanup)) {
          			if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          				busy = false;
          				return;
          			}
          		}
          
          		fancybox_abort();
          
          		$(close.add( nav_left ).add( nav_right )).hide();
          
          		$('#fancybox-title').remove();
          
          		wrap.add(inner).add(overlay).unbind();
          
          		$(window).unbind("resize.fb scroll.fb");
          		$(document).unbind('keydown.fb');
          
          		function _cleanup() {
          			overlay.fadeOut('fast');
          
          			wrap.hide();
          
          			$.event.trigger('fancybox-cleanup');
          
          			inner.empty();
          
          			if ($.isFunction(currentOpts.onClosed)) {
          				currentOpts.onClosed(currentArray, currentIndex, currentOpts);
          			}
          
          			currentArray	= selectedOpts	= [];
          			currentIndex	= selectedIndex	= 0;
          			currentOpts		= selectedOpts	= {};
          
          			busy = false;
          		}
          
          		inner.css('overflow', 'hidden');
          
          		if (currentOpts.transitionOut == 'elastic') {
          			start_pos = fancybox_get_zoom_from();
          
          			var pos = wrap.position();
          
          			final_pos = {
          				top		:	pos.top ,
          				left	:	pos.left,
          				width	:	wrap.width(),
          				height	:	wrap.height()
          			};
          
          			if (currentOpts.opacity) {
          				final_pos.opacity = 1;
          			}
          
          			fx.prop = 1;
          
          			$(fx).animate({ prop: 0 }, {
          				 duration	: currentOpts.speedOut,
          				 easing		: currentOpts.easingOut,
          				 step		: fancybox_draw,
          				 complete	: _cleanup
          			});
          
          		} else {
          			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
          		}
          	};
          
          	$.fancybox.resize = function() {
          		var c, h;
          		
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		c = inner.wrapInner("<div style='overflow:auto'></div>").children();
          		h = c.height();
          
          		wrap.css({height:	h + (currentOpts.padding * 2) + titleh});
          		inner.css({height:	h});
          
          		c.replaceWith(c.children());
          
          		$.fancybox.center();
          	};
          
          	$.fancybox.center = function() {
          		busy = true;
          
          		var view	= fancybox_get_viewport(),
          			margin	= currentOpts.margin,
          			to		= {};
          
          		to.top	= view[3] + ((view[1] - ((wrap.height() - titleh) + (shadow * 2 ))) * 0.5);
          		to.left	= view[2] + ((view[0] - (wrap.width() + (shadow * 2 ))) * 0.5);
          
          		to.top	= Math.max(view[3] + margin, to.top);
          		to.left	= Math.max(view[2] + margin, to.left);
          
          		wrap.css(to);
          
          		busy = false;
          	};
          
          	$.fn.fancybox.defaults = {
          		padding				:	10,
          		margin				:	20,
          		opacity				:	false,
          		modal				:	false,
          		cyclic				:	false,
          		scrolling			:	'auto',	// 'auto', 'yes' or 'no'
          
          		width				:	560,
          		height				:	340,
          
          		autoScale			:	true,
          		autoDimensions		:	true,
          		centerOnScroll		:	false,
          
          		ajax				:	{},
          		swf					:	{ wmode: 'transparent' },
          
          		hideOnOverlayClick	:	true,
          		hideOnContentClick	:	false,
          
          		overlayShow			:	true,
          		overlayOpacity		:	0.3,
          		overlayColor		:	'#666',
          
          		titleShow			:	true,
          		titlePosition		:	'outside',	// 'outside', 'inside' or 'over'
          		titleFormat			:	null,
          
          		transitionIn		:	'fade',	// 'elastic', 'fade' or 'none'
          		transitionOut		:	'fade',	// 'elastic', 'fade' or 'none'
          
          		speedIn				:	300,
          		speedOut			:	300,
          
          		changeSpeed			:	300,
          		changeFade			:	'fast',
          
          		easingIn			:	'swing',
          		easingOut			:	'swing',
          
          		showCloseButton		:	true,
          		showNavArrows		:	true,
          		enableEscapeButton	:	true,
          
          		onStart				:	null,
          		onCancel			:	null,
          		onComplete			:	null,
          		onCleanup			:	null,
          		onClosed			:	null
          	};
          
          	$(document).ready(function() {
          		fancybox_init();
          	});
          
          })(jQuery);
          Evidence
          later
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        29. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bSELECT\b and was detected in the element starting with: " $('select:not(#fancybox-tmp select)').filter(function() { ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (418 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:56 GMT
          Content-Type: application/javascript
          Content-Length: 28094
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"28094-1267813320000"
          Last-Modified: Fri, 05 Mar 2010 18:22:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (28094 bytes)
          /*
           * FancyBox - jQuery Plugin
           * Simple and fancy lightbox alternative
           *
           * Examples and documentation at: http://fancybox.net
           * 
           * Copyright (c) 2008 - 2010 Janis Skarnelis
           *
           * Version: 1.3.1 (05/03/2010)
           * Requires: jQuery v1.3+
           *
           * Dual licensed under the MIT and GPL licenses:
           *   http://www.opensource.org/licenses/mit-license.php
           *   http://www.gnu.org/licenses/gpl.html
           */
          
          (function($) {
          
          	var tmp, loading, overlay, wrap, outer, inner, close, nav_left, nav_right,
          
          		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
          
          		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
          
          		loadingTimer, loadingFrame = 1,
          
          		start_pos, final_pos, busy = false, shadow = 20, fx = $.extend($('<div/>')[0], { prop: 0 }), titleh = 0, 
          
          		isIE6 = !$.support.opacity && !window.XMLHttpRequest,
          
          		/*
          		 * Private methods 
          		 */
          
          		fancybox_abort = function() {
          			loading.hide();
          
          			imgPreloader.onerror = imgPreloader.onload = null;
          
          			if (ajaxLoader) {
          				ajaxLoader.abort();
          			}
          
          			tmp.empty();
          		},
          
          		fancybox_error = function() {
          			$.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', {
          				'scrolling'		: 'no',
          				'padding'		: 20,
          				'transitionIn'	: 'none',
          				'transitionOut'	: 'none'
          			});
          		},
          
          		fancybox_get_viewport = function() {
          			return [ $(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ];
          		},
          
          		fancybox_get_zoom_to = function () {
          			var view	= fancybox_get_viewport(),
          				to		= {},
          
          				margin = currentOpts.margin,
          				resize = currentOpts.autoScale,
          
          				horizontal_space	= (shadow + margin) * 2,
          				vertical_space		= (shadow + margin) * 2,
          				double_padding		= (currentOpts.padding * 2),
          				
          				ratio;
          
          			if (currentOpts.width.toString().indexOf('%') > -1) {
          				to.width = ((view[0] * parseFloat(currentOpts.width)) / 100) - (shadow * 2) ;
          				resize = false;
          
          			} else {
          				to.width = currentOpts.width + double_padding;
          			}
          
          			if (currentOpts.height.toString().indexOf('%') > -1) {
          				to.height = ((view[1] * parseFloat(currentOpts.height)) / 100) - (shadow * 2);
          				resize = false;
          
          			} else {
          				to.height = currentOpts.height + double_padding;
          			}
          
          			if (resize && (to.width > (view[0] - horizontal_space) || to.height > (view[1] - vertical_space))) {
          				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
          					horizontal_space	+= double_padding;
          					vertical_space		+= double_padding;
          
          					ratio = Math.min(Math.min( view[0] - horizontal_space, currentOpts.width) / currentOpts.width, Math.min( view[1] - vertical_space, currentOpts.height) / currentOpts.height);
          
          					to.width	= Math.round(ratio * (to.width	- double_padding)) + double_padding;
          					to.height	= Math.round(ratio * (to.height	- double_padding)) + double_padding;
          
          				} else {
          					to.width	= Math.min(to.width,	(view[0] - horizontal_space));
          					to.height	= Math.min(to.height,	(view[1] - vertical_space));
          				}
          			}
          
          			to.top	= view[3] + ((view[1] - (to.height	+ (shadow * 2 ))) * 0.5);
          			to.left	= view[2] + ((view[0] - (to.width	+ (shadow * 2 ))) * 0.5);
          
          			if (currentOpts.autoScale === false) {
          				to.top	= Math.max(view[3] + margin, to.top);
          				to.left	= Math.max(view[2] + margin, to.left);
          			}
          
          			return to;
          		},
          
          		fancybox_format_title = function(title) {
          			if (title && title.length) {
          				switch (currentOpts.titlePosition) {
          					case 'inside':
          						return title;
          					case 'over':
          						return '<span id="fancybox-title-over">' + title + '</span>';
          					default:
          						return '<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">' + title + '</span><span id="fancybox-title-right"></span></span>';
          				}
          			}
          
          			return false;
          		},
          
          		fancybox_process_title = function() {
          			var title	= currentOpts.title,
          				width	= final_pos.width - (currentOpts.padding * 2),
          				titlec	= 'fancybox-title-' + currentOpts.titlePosition;
          				
          			$('#fancybox-title').remove();
          
          			titleh = 0;
          
          			if (currentOpts.titleShow === false) {
          				return;
          			}
          
          			title = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(title, currentArray, currentIndex, currentOpts) : fancybox_format_title(title);
          
          			if (!title || title === '') {
          				return;
          			}
          
          			$('<div id="fancybox-title" class="' + titlec + '" />').css({
          				'width'			: width,
          				'paddingLeft'	: currentOpts.padding,
          				'paddingRight'	: currentOpts.padding
          			}).html(title).appendTo('body');
          
          			switch (currentOpts.titlePosition) {
          				case 'inside':
          					titleh = $("#fancybox-title").outerHeight(true) - currentOpts.padding;
          					final_pos.height += titleh;
          				break;
          
          				case 'over':
          					$('#fancybox-title').css('bottom', currentOpts.padding);
          				break;
          
          				default:
          					$('#fancybox-title').css('bottom', $("#fancybox-title").outerHeight(true) * -1);
          				break;
          			}
          
          			$('#fancybox-title').appendTo( outer ).hide();
          		},
          
          		fancybox_set_navigation = function() {
          			$(document).unbind('keydown.fb').bind('keydown.fb', function(e) {
          				if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
          					e.preventDefault();
          					$.fancybox.close();
          
          				} else if (e.keyCode == 37) {
          					e.preventDefault();
          					$.fancybox.prev();
          
          				} else if (e.keyCode == 39) {
          					e.preventDefault();
          					$.fancybox.next();
          				}
          			});
          
          			if ($.fn.mousewheel) {
          				wrap.unbind('mousewheel.fb');
          
          				if (currentArray.length > 1) {
          					wrap.bind('mousewheel.fb', function(e, delta) {
          						e.preventDefault();
          
          						if (busy || delta === 0) {
          							return;
          						}
          
          						if (delta > 0) {
          							$.fancybox.prev();
          						} else {
          							$.fancybox.next();
          						}
          					});
          				}
          			}
          
          			if (!currentOpts.showNavArrows) { return; }
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
          				nav_left.show();
          			}
          
          			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
          				nav_right.show();
          			}
          		},
          
          		fancybox_preload_images = function() {
          			var href, 
          				objNext;
          				
          			if ((currentArray.length -1) > currentIndex) {
          				href = currentArray[ currentIndex + 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          
          			if (currentIndex > 0) {
          				href = currentArray[ currentIndex - 1 ].href;
          
          				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
          					objNext = new Image();
          					objNext.src = href;
          				}
          			}
          		},
          
          		_finish = function () {
          			inner.css('overflow', (currentOpts.scrolling == 'auto' ? (currentOpts.type == 'image' || currentOpts.type == 'iframe' || currentOpts.type == 'swf' ? 'hidden' : 'auto') : (currentOpts.scrolling == 'yes' ? 'auto' : 'visible')));
          
          			if (!$.support.opacity) {
          				inner.get(0).style.removeAttribute('filter');
          				wrap.get(0).style.removeAttribute('filter');
          			}
          
          			$('#fancybox-title').show();
          
          			if (currentOpts.hideOnContentClick)	{
          				inner.one('click', $.fancybox.close);
          			}
          			if (currentOpts.hideOnOverlayClick)	{
          				overlay.one('click', $.fancybox.close);
          			}
          
          			if (currentOpts.showCloseButton) {
          				close.show();
          			}
          
          			fancybox_set_navigation();
          
          			$(window).bind("resize.fb", $.fancybox.center);
          
          			if (currentOpts.centerOnScroll) {
          				$(window).bind("scroll.fb", $.fancybox.center);
          			} else {
          				$(window).unbind("scroll.fb");
          			}
          
          			if ($.isFunction(currentOpts.onComplete)) {
          				currentOpts.onComplete(currentArray, currentIndex, currentOpts);
          			}
          
          			busy = false;
          
          			fancybox_preload_images();
          		},
          
          		fancybox_draw = function(pos) {
          			var width	= Math.round(start_pos.width	+ (final_pos.width	- start_pos.width)	* pos),
          				height	= Math.round(start_pos.height	+ (final_pos.height	- start_pos.height)	* pos),
          
          				top		= Math.round(start_pos.top	+ (final_pos.top	- start_pos.top)	* pos),
          				left	= Math.round(start_pos.left	+ (final_pos.left	- start_pos.left)	* pos);
          
          			wrap.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px',
          				'top'		: top		+ 'px',
          				'left'		: left		+ 'px'
          			});
          
          			width	= Math.max(width - currentOpts.padding * 2, 0);
          			height	= Math.max(height - (currentOpts.padding * 2 + (titleh * pos)), 0);
          
          			inner.css({
          				'width'		: width		+ 'px',
          				'height'	: height	+ 'px'
          			});
          
          			if (typeof final_pos.opacity !== 'undefined') {
          				wrap.css('opacity', (pos < 0.5 ? 0.5 : pos));
          			}
          		},
          
          		fancybox_get_obj_pos = function(obj) {
          			var pos		= obj.offset();
          
          			pos.top		+= parseFloat( obj.css('paddingTop') )	|| 0;
          			pos.left	+= parseFloat( obj.css('paddingLeft') )	|| 0;
          
          			pos.top		+= parseFloat( obj.css('border-top-width') )	|| 0;
          			pos.left	+= parseFloat( obj.css('border-left-width') )	|| 0;
          
          			pos.width	= obj.width();
          			pos.height	= obj.height();
          
          			return pos;
          		},
          
          		fancybox_get_zoom_from = function() {
          			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
          				from = {},
          				pos,
          				view;
          
          			if (orig && orig.length) {
          				pos = fancybox_get_obj_pos(orig);
          
          				from = {
          					width	: (pos.width	+ (currentOpts.padding * 2)),
          					height	: (pos.height	+ (currentOpts.padding * 2)),
          					top		: (pos.top		- currentOpts.padding - shadow),
          					left	: (pos.left		- currentOpts.padding - shadow)
          				};
          				
          			} else {
          				view = fancybox_get_viewport();
          
          				from = {
          					width	: 1,
          					height	: 1,
          					top		: view[3] + view[1] * 0.5,
          					left	: view[2] + view[0] * 0.5
          				};
          			}
          
          			return from;
          		},
          
          		fancybox_show = function() {
          			loading.hide();
          
          			if (wrap.is(":visible") && $.isFunction(currentOpts.onCleanup)) {
          				if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          					$.event.trigger('fancybox-cancel');
          
          					busy = false;
          					return;
          				}
          			}
          
          			currentArray	= selectedArray;
          			currentIndex	= selectedIndex;
          			currentOpts		= selectedOpts;
          
          			inner.get(0).scrollTop	= 0;
          			inner.get(0).scrollLeft	= 0;
          
          			if (currentOpts.overlayShow) {
          				if (isIE6) {
          					$('select:not(#fancybox-tmp select)').filter(function() {
          						return this.style.visibility !== 'hidden';
          					}).css({'visibility':'hidden'}).one('fancybox-cleanup', function() {
          						this.style.visibility = 'inherit';
          					});
          				}
          
          				overlay.css({
          					'background-color'	: currentOpts.overlayColor,
          					'opacity'			: currentOpts.overlayOpacity
          				}).unbind().show();
          			}
          
          			final_pos = fancybox_get_zoom_to();
          
          			fancybox_process_title();
          
          			if (wrap.is(":visible")) {
          				$( close.add( nav_left ).add( nav_right ) ).hide();
          
          				var pos = wrap.position(),
          					equal;
          
          				start_pos = {
          					top		:	pos.top ,
          					left	:	pos.left,
          					width	:	wrap.width(),
          					height	:	wrap.height()
          				};
          
          				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
          
          				inner.fadeOut(currentOpts.changeFade, function() {
          					var finish_resizing = function() {
          						inner.html( tmp.contents() ).fadeIn(currentOpts.changeFade, _finish);
          					};
          					
          					$.event.trigger('fancybox-change');
          
          					inner.empty().css('overflow', 'hidden');
          
          					if (equal) {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          						});
          						
          						finish_resizing();
          
          					} else {
          						inner.css({
          							top			: currentOpts.padding,
          							left		: currentOpts.padding,
          							width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          							height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          						});
          						
          						fx.prop = 0;
          
          						$(fx).animate({ prop: 1 }, {
          							 duration	: currentOpts.changeSpeed,
          							 easing		: currentOpts.easingChange,
          							 step		: fancybox_draw,
          							 complete	: finish_resizing
          						});
          					}
          				});
          
          				return;
          			}
          
          			wrap.css('opacity', 1);
          
          			if (currentOpts.transitionIn == 'elastic') {
          				start_pos = fancybox_get_zoom_from();
          
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css(start_pos).show();
          
          				if (currentOpts.opacity) {
          					final_pos.opacity = 0;
          				}
          
          				fx.prop = 0;
          
          				$(fx).animate({ prop: 1 }, {
          					 duration	: currentOpts.speedIn,
          					 easing		: currentOpts.easingIn,
          					 step		: fancybox_draw,
          					 complete	: _finish
          				});
          
          			} else {
          				inner.css({
          						top			: currentOpts.padding,
          						left		: currentOpts.padding,
          						width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
          						height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
          					})
          					.html( tmp.contents() );
          
          				wrap.css( final_pos ).fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
          			}
          		},
          
          		fancybox_process_inline = function() {
          			tmp.width(	selectedOpts.width );
          			tmp.height(	selectedOpts.height );
          
          			if (selectedOpts.width	== 'auto') {
          				selectedOpts.width = tmp.width();
          			}
          			if (selectedOpts.height	== 'auto') {
          				selectedOpts.height	= tmp.height();
          			}
          
          			fancybox_show();
          		},
          		
          		fancybox_process_image = function() {
          			busy = true;
          
          			selectedOpts.width	= imgPreloader.width;
          			selectedOpts.height	= imgPreloader.height;
          
          			$("<img />").attr({
          				'id'	: 'fancybox-img',
          				'src'	: imgPreloader.src,
          				'alt'	: selectedOpts.title
          			}).appendTo( tmp );
          
          			fancybox_show();
          		},
          
          		fancybox_start = function() {
          			fancybox_abort();
          
          			var obj	= selectedArray[ selectedIndex ],
          				href, 
          				type, 
          				title,
          				str,
          				emb,
          				selector,
          				data;
          
          			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
          			title = obj.title || $(obj).title || selectedOpts.title || '';
          			
          			if (obj.nodeName && !selectedOpts.orig) {
          				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
          			}
          
          			if (title === '' && selectedOpts.orig) {
          				title = selectedOpts.orig.attr('alt');
          			}
          
          			if (obj.nodeName && (/^(?:javascript|#)/i).test(obj.href)) {
          				href = selectedOpts.href || null;
          			} else {
          				href = selectedOpts.href || obj.href || null;
          			}
          
          			if (selectedOpts.type) {
          				type = selectedOpts.type;
          
          				if (!href) {
          					href = selectedOpts.content;
          				}
          				
          			} else if (selectedOpts.content) {
          				type	= 'html';
          
          			} else if (href) {
          				if (href.match(imgRegExp)) {
          					type = 'image';
          
          				} else if (href.match(swfRegExp)) {
          					type = 'swf';
          
          				} else if ($(obj).hasClass("iframe")) {
          					type = 'iframe';
          
          				} else if (href.match(/#/)) {
          					obj = href.substr(href.indexOf("#"));
          
          					type = $(obj).length > 0 ? 'inline' : 'ajax';
          				} else {
          					type = 'ajax';
          				}
          			} else {
          				type = 'inline';
          			}
          
          			selectedOpts.type	= type;
          			selectedOpts.href	= href;
          			selectedOpts.title	= title;
          
          			if (selectedOpts.autoDimensions && selectedOpts.type !== 'iframe' && selectedOpts.type !== 'swf') {
          				selectedOpts.width		= 'auto';
          				selectedOpts.height		= 'auto';
          			}
          
          			if (selectedOpts.modal) {
          				selectedOpts.overlayShow		= true;
          				selectedOpts.hideOnOverlayClick	= false;
          				selectedOpts.hideOnContentClick	= false;
          				selectedOpts.enableEscapeButton	= false;
          				selectedOpts.showCloseButton	= false;
          			}
          
          			if ($.isFunction(selectedOpts.onStart)) {
          				if (selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts) === false) {
          					busy = false;
          					return;
          				}
          			}
          
          			tmp.css('padding', (shadow + selectedOpts.padding + selectedOpts.margin));
          
          			$('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
          				$(this).replaceWith(inner.children());
          			});
          
          			switch (type) {
          				case 'html' :
          					tmp.html( selectedOpts.content );
          					fancybox_process_inline();
          				break;
          
          				case 'inline' :
          					$('<div class="fancybox-inline-tmp" />').hide().insertBefore( $(obj) ).bind('fancybox-cleanup', function() {
          						$(this).replaceWith(inner.children());
          					}).bind('fancybox-cancel', function() {
          						$(this).replaceWith(tmp.children());
          					});
          
          					$(obj).appendTo(tmp);
          
          					fancybox_process_inline();
          				break;
          
          				case 'image':
          					busy = false;
          
          					$.fancybox.showActivity();
          
          					imgPreloader = new Image();
          
          					imgPreloader.onerror = function() {
          						fancybox_error();
          					};
          
          					imgPreloader.onload = function() {
          						imgPreloader.onerror = null;
          						imgPreloader.onload = null;
          						fancybox_process_image();
          					};
          
          					imgPreloader.src = href;
          		
          				break;
          
          				case 'swf':
          					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
          					emb = '';
          					
          					$.each(selectedOpts.swf, function(name, val) {
          						str += '<param name="' + name + '" value="' + val + '"></param>';
          						emb += ' ' + name + '="' + val + '"';
          					});
          
          					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
          
          					tmp.html(str);
          
          					fancybox_process_inline();
          				break;
          
          				case 'ajax':
          					selector	= href.split('#', 2);
          					data		= selectedOpts.ajax.data || {};
          
          					if (selector.length > 1) {
          						href = selector[0];
          
          						if (typeof data == "string") {
          							data += '&selector=' + selector[1];
          						} else {
          							data.selector = selector[1];
          						}
          					}
          
          					busy = false;
          					$.fancybox.showActivity();
          
          					ajaxLoader = $.ajax($.extend(selectedOpts.ajax, {
          						url		: href,
          						data	: data,
          						error	: fancybox_error,
          						success : function(data, textStatus, XMLHttpRequest) {
          							if (ajaxLoader.status == 200) {
          								tmp.html( data );
          								fancybox_process_inline();
          							}
          						}
          					}));
          
          				break;
          
          				case 'iframe' :
          					$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" scrolling="' + selectedOpts.scrolling + '" src="' + selectedOpts.href + '"></iframe>').appendTo(tmp);
          					fancybox_show();
          				break;
          			}
          		},
          
          		fancybox_animate_loading = function() {
          			if (!loading.is(':visible')){
          				clearInterval(loadingTimer);
          				return;
          			}
          
          			$('div', loading).css('top', (loadingFrame * -40) + 'px');
          
          			loadingFrame = (loadingFrame + 1) % 12;
          		},
          
          		fancybox_init = function() {
          			if ($("#fancybox-wrap").length) {
          				return;
          			}
          
          			$('body').append(
          				tmp			= $('<div id="fancybox-tmp"></div>'),
          				loading		= $('<div id="fancybox-loading"><div></div></div>'),
          				overlay		= $('<div id="fancybox-overlay"></div>'),
          				wrap		= $('<div id="fancybox-wrap"></div>')
          			);
          
          			if (!$.support.opacity) {
          				wrap.addClass('fancybox-ie');
          				loading.addClass('fancybox-ie');
          			}
          
          			outer = $('<div id="fancybox-outer"></div>')
          				.append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>')
          				.appendTo( wrap );
          
          			outer.append(
          				inner		= $('<div id="fancybox-inner"></div>'),
          				close		= $('<a id="fancybox-close"></a>'),
          
          				nav_left	= $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
          				nav_right	= $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
          			);
          
          			close.click($.fancybox.close);
          			loading.click($.fancybox.cancel);
          
          			nav_left.click(function(e) {
          				e.preventDefault();
          				$.fancybox.prev();
          			});
          
          			nav_right.click(function(e) {
          				e.preventDefault();
          				$.fancybox.next();
          			});
          
          			if (isIE6) {
          				overlay.get(0).style.setExpression('height',	"document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");
          				loading.get(0).style.setExpression('top',		"(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");
          
          				outer.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>');
          			}
          		};
          
          	/*
          	 * Public methods 
          	 */
          
          	$.fn.fancybox = function(options) {
          		$(this)
          			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
          			.unbind('click.fb').bind('click.fb', function(e) {
          				e.preventDefault();
          
          				if (busy) {
          					return;
          				}
          
          				busy = true;
          
          				$(this).blur();
          
          				selectedArray	= [];
          				selectedIndex	= 0;
          
          				var rel = $(this).attr('rel') || '';
          
          				if (!rel || rel == '' || rel === 'nofollow') {
          					selectedArray.push(this);
          
          				} else {
          					selectedArray	= $("a[rel=" + rel + "], area[rel=" + rel + "]");
          					selectedIndex	= selectedArray.index( this );
          				}
          
          				fancybox_start();
          
          				return false;
          			});
          
          		return this;
          	};
          
          	$.fancybox = function(obj) {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		var opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
          
          		selectedArray	= [];
          		selectedIndex	= opts.index || 0;
          
          		if ($.isArray(obj)) {
          			for (var i = 0, j = obj.length; i < j; i++) {
          				if (typeof obj[i] == 'object') {
          					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
          				} else {
          					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
          				}
          			}
          
          			selectedArray = jQuery.merge(selectedArray, obj);
          
          		} else {
          			if (typeof obj == 'object') {
          				$(obj).data('fancybox', $.extend({}, opts, obj));
          			} else {
          				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
          			}
          
          			selectedArray.push(obj);
          		}
          
          		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
          			selectedIndex = 0;
          		}
          
          		fancybox_start();
          	};
          
          	$.fancybox.showActivity = function() {
          		clearInterval(loadingTimer);
          
          		loading.show();
          		loadingTimer = setInterval(fancybox_animate_loading, 66);
          	};
          
          	$.fancybox.hideActivity = function() {
          		loading.hide();
          	};
          
          	$.fancybox.next = function() {
          		return $.fancybox.pos( currentIndex + 1);
          	};
          	
          	$.fancybox.prev = function() {
          		return $.fancybox.pos( currentIndex - 1);
          	};
          
          	$.fancybox.pos = function(pos) {
          		if (busy) {
          			return;
          		}
          
          		pos = parseInt(pos, 10);
          
          		if (pos > -1 && currentArray.length > pos) {
          			selectedIndex = pos;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos < 0) {
          			selectedIndex = currentArray.length - 1;
          			fancybox_start();
          		}
          
          		if (currentOpts.cyclic && currentArray.length > 1 && pos >= currentArray.length) {
          			selectedIndex = 0;
          			fancybox_start();
          		}
          
          		return;
          	};
          
          	$.fancybox.cancel = function() {
          		if (busy) {
          			return;
          		}
          
          		busy = true;
          
          		$.event.trigger('fancybox-cancel');
          
          		fancybox_abort();
          
          		if (selectedOpts && $.isFunction(selectedOpts.onCancel)) {
          			selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
          		}
          
          		busy = false;
          	};
          
          	// Note: within an iframe use - parent.$.fancybox.close();
          	$.fancybox.close = function() {
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		if (currentOpts && $.isFunction(currentOpts.onCleanup)) {
          			if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
          				busy = false;
          				return;
          			}
          		}
          
          		fancybox_abort();
          
          		$(close.add( nav_left ).add( nav_right )).hide();
          
          		$('#fancybox-title').remove();
          
          		wrap.add(inner).add(overlay).unbind();
          
          		$(window).unbind("resize.fb scroll.fb");
          		$(document).unbind('keydown.fb');
          
          		function _cleanup() {
          			overlay.fadeOut('fast');
          
          			wrap.hide();
          
          			$.event.trigger('fancybox-cleanup');
          
          			inner.empty();
          
          			if ($.isFunction(currentOpts.onClosed)) {
          				currentOpts.onClosed(currentArray, currentIndex, currentOpts);
          			}
          
          			currentArray	= selectedOpts	= [];
          			currentIndex	= selectedIndex	= 0;
          			currentOpts		= selectedOpts	= {};
          
          			busy = false;
          		}
          
          		inner.css('overflow', 'hidden');
          
          		if (currentOpts.transitionOut == 'elastic') {
          			start_pos = fancybox_get_zoom_from();
          
          			var pos = wrap.position();
          
          			final_pos = {
          				top		:	pos.top ,
          				left	:	pos.left,
          				width	:	wrap.width(),
          				height	:	wrap.height()
          			};
          
          			if (currentOpts.opacity) {
          				final_pos.opacity = 1;
          			}
          
          			fx.prop = 1;
          
          			$(fx).animate({ prop: 0 }, {
          				 duration	: currentOpts.speedOut,
          				 easing		: currentOpts.easingOut,
          				 step		: fancybox_draw,
          				 complete	: _cleanup
          			});
          
          		} else {
          			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
          		}
          	};
          
          	$.fancybox.resize = function() {
          		var c, h;
          		
          		if (busy || wrap.is(':hidden')) {
          			return;
          		}
          
          		busy = true;
          
          		c = inner.wrapInner("<div style='overflow:auto'></div>").children();
          		h = c.height();
          
          		wrap.css({height:	h + (currentOpts.padding * 2) + titleh});
          		inner.css({height:	h});
          
          		c.replaceWith(c.children());
          
          		$.fancybox.center();
          	};
          
          	$.fancybox.center = function() {
          		busy = true;
          
          		var view	= fancybox_get_viewport(),
          			margin	= currentOpts.margin,
          			to		= {};
          
          		to.top	= view[3] + ((view[1] - ((wrap.height() - titleh) + (shadow * 2 ))) * 0.5);
          		to.left	= view[2] + ((view[0] - (wrap.width() + (shadow * 2 ))) * 0.5);
          
          		to.top	= Math.max(view[3] + margin, to.top);
          		to.left	= Math.max(view[2] + margin, to.left);
          
          		wrap.css(to);
          
          		busy = false;
          	};
          
          	$.fn.fancybox.defaults = {
          		padding				:	10,
          		margin				:	20,
          		opacity				:	false,
          		modal				:	false,
          		cyclic				:	false,
          		scrolling			:	'auto',	// 'auto', 'yes' or 'no'
          
          		width				:	560,
          		height				:	340,
          
          		autoScale			:	true,
          		autoDimensions		:	true,
          		centerOnScroll		:	false,
          
          		ajax				:	{},
          		swf					:	{ wmode: 'transparent' },
          
          		hideOnOverlayClick	:	true,
          		hideOnContentClick	:	false,
          
          		overlayShow			:	true,
          		overlayOpacity		:	0.3,
          		overlayColor		:	'#666',
          
          		titleShow			:	true,
          		titlePosition		:	'outside',	// 'outside', 'inside' or 'over'
          		titleFormat			:	null,
          
          		transitionIn		:	'fade',	// 'elastic', 'fade' or 'none'
          		transitionOut		:	'fade',	// 'elastic', 'fade' or 'none'
          
          		speedIn				:	300,
          		speedOut			:	300,
          
          		changeSpeed			:	300,
          		changeFade			:	'fast',
          
          		easingIn			:	'swing',
          		easingOut			:	'swing',
          
          		showCloseButton		:	true,
          		showNavArrows		:	true,
          		enableEscapeButton	:	true,
          
          		onStart				:	null,
          		onCancel			:	null,
          		onComplete			:	null,
          		onCleanup			:	null,
          		onClosed			:	null
          	};
          
          	$(document).ready(function() {
          		fancybox_init();
          	});
          
          })(jQuery);
          Evidence
          select
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        30. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.form.min.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bSELECT\b and was detected in the element starting with: ";(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(this).ajaxSubmit(r))}functio", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (381 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.form.min.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 14504
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"14504-1371572158000"
          Last-Modified: Tue, 18 Jun 2013 16:15:58 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (14504 bytes)
          /*
          * jQuery Form Plugin; v20130616
          * http://jquery.malsup.com/form/
          * Copyright (c) 2013 M. Alsup; Dual licensed: MIT/GPL
          * https://github.com/malsup/form#copyright-and-license
          */
          ;(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(this).ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=this;if(i.clk=r,"image"==r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n={};n.fileapi=void 0!==e("<input type='file'/>").get(0).files,n.formdata=void 0!==window.FormData;var i=!!e.fn.prop;e.fn.attr2=function(){if(!i)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t){function r(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;o>a;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function o(a){for(var n=new FormData,i=0;a.length>i;i++)n.append(a[i].name,a[i].value);if(t.extraData){var o=r(t.extraData);for(i=0;o.length>i;i++)o[i]&&n.append(o[i][0],o[i][1])}t.data=null;var s=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:u||"POST"});t.uploadProgress&&(s.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(100*(a/n))),t.uploadProgress(e,a,n,r)},!1),r}),s.data=null;var l=s.beforeSend;return s.beforeSend=function(e,t){t.data=n,l&&l.call(this,e,t)},e.ajax(s)}function s(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(r){a("cannot get iframe.contentWindow document: "+r)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function o(){function t(){try{var e=n(g).readyState;a("state = "+e),e&&"uninitialized"==e.toLowerCase()&&setTimeout(t,50)}catch(r){a("Server abort: ",r," (",r.name,")"),s(D),j&&clearTimeout(j),j=void 0}}var r=f.attr2("target"),i=f.attr2("action");w.setAttribute("target",d),u||w.setAttribute("method","POST"),i!=m.url&&w.setAttribute("action",m.url),m.skipEncodingOverride||u&&!/post/i.test(u)||f.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),m.timeout&&(j=setTimeout(function(){T=!0,s(k)},m.timeout));var o=[];try{if(m.extraData)for(var l in m.extraData)m.extraData.hasOwnProperty(l)&&(e.isPlainObject(m.extraData[l])&&m.extraData[l].hasOwnProperty("name")&&m.extraData[l].hasOwnProperty("value")?o.push(e('<input type="hidden" name="'+m.extraData[l].name+'">').val(m.extraData[l].value).appendTo(w)[0]):o.push(e('<input type="hidden" name="'+l+'">').val(m.extraData[l]).appendTo(w)[0]));m.iframeTarget||(v.appendTo("body"),g.attachEvent?g.attachEvent("onload",s):g.addEventListener("load",s,!1)),setTimeout(t,15);try{w.submit()}catch(c){var p=document.createElement("form").submit;p.apply(w)}}finally{w.setAttribute("action",i),r?w.setAttribute("target",r):f.removeAttr("target"),e(o).remove()}}function s(t){if(!x.aborted&&!F){if(M=n(g),M||(a("cannot access response document"),t=D),t===k&&x)return x.abort("timeout"),S.reject(x,"timeout"),void 0;if(t==D&&x)return x.abort("server abort"),S.reject(x,"error","server abort"),void 0;if(M&&M.location.href!=m.iframeSrc||T){g.detachEvent?g.detachEvent("onload",s):g.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"==m.dataType||M.XMLDocument||e.isXMLDoc(M);if(a("isXml="+o),!o&&window.opera&&(null===M.body||!M.body.innerHTML)&&--O)return a("requeing onLoad callback, DOM not available"),setTimeout(s,250),void 0;var u=M.body?M.body:M.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=M.XMLDocument?M.XMLDocument:M,o&&(m.dataType="xml"),x.getResponseHeader=function(e){var t={"content-type":m.dataType};return t[e]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var l=(m.dataType||"").toLowerCase(),c=/(json|script|text)/.test(l);if(c||m.textarea){var f=M.getElementsByTagName("textarea")[0];if(f)x.responseText=f.value,x.status=Number(f.getAttribute("status"))||x.status,x.statusText=f.getAttribute("statusText")||x.statusText;else if(c){var d=M.getElementsByTagName("pre")[0],h=M.getElementsByTagName("body")[0];d?x.responseText=d.textContent?d.textContent:d.innerText:h&&(x.responseText=h.textContent?h.textContent:h.innerText)}}else"xml"==l&&!x.responseXML&&x.responseText&&(x.responseXML=X(x.responseText));try{L=_(x,l,m)}catch(b){i="parsererror",x.error=r=b||i}}catch(b){a("error caught: ",b),i="error",x.error=r=b||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&300>x.status||304===x.status?"success":"error"),"success"===i?(m.success&&m.success.call(m.context,L,"success",x),S.resolve(x.responseText,"success",x),p&&e.event.trigger("ajaxSuccess",[x,m])):i&&(void 0===r&&(r=x.statusText),m.error&&m.error.call(m.context,x,i,r),S.reject(x,"error",r),p&&e.event.trigger("ajaxError",[x,m,r])),p&&e.event.trigger("ajaxComplete",[x,m]),p&&!--e.active&&e.event.trigger("ajaxStop"),m.complete&&m.complete.call(m.context,x,i),F=!0,m.timeout&&clearTimeout(j),setTimeout(function(){m.iframeTarget||v.remove(),x.responseXML=null},100)}}}var l,c,m,p,d,v,g,x,b,y,T,j,w=f[0],S=e.Deferred();if(r)for(c=0;h.length>c;c++)l=e(h[c]),i?l.prop("disabled",!1):l.removeAttr("disabled");if(m=e.extend(!0,{},e.ajaxSettings,t),m.context=m.context||m,d="jqFormIO"+(new Date).getTime(),m.iframeTarget?(v=e(m.iframeTarget),y=v.attr2("name"),y?d=y:v.attr2("name",d)):(v=e('<iframe name="'+d+'" src="'+m.iframeSrc+'" />'),v.css({position:"absolute",top:"-1000px",left:"-1000px"})),g=v[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{g.contentWindow.document.execCommand&&g.contentWindow.document.execCommand("Stop")}catch(n){}v.attr("src",m.iframeSrc),x.error=r,m.error&&m.error.call(m.context,x,r,t),p&&e.event.trigger("ajaxError",[x,m,r]),m.complete&&m.complete.call(m.context,x,r)}},p=m.global,p&&0===e.active++&&e.event.trigger("ajaxStart"),p&&e.event.trigger("ajaxSend",[x,m]),m.beforeSend&&m.beforeSend.call(m.context,x,m)===!1)return m.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;b=w.clk,b&&(y=b.name,y&&!b.disabled&&(m.extraData=m.extraData||{},m.extraData[y]=b.value,"image"==b.type&&(m.extraData[y+".x"]=w.clk_x,m.extraData[y+".y"]=w.clk_y)));var k=1,D=2,A=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&A&&(m.extraData=m.extraData||{},m.extraData[E]=A),m.forceSync?o():setTimeout(o,10);var L,M,F,O=50,X=e.parseXML||function(e,t){return window.ActiveXObject?(t=new ActiveXObject("Microsoft.XMLDOM"),t.async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!=t.documentElement.nodeName?t:null},C=e.parseJSON||function(e){return window.eval("("+e+")")},_=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i="xml"===r||!r&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&("json"===r||!r&&n.indexOf("json")>=0?o=C(o):("script"===r||!r&&n.indexOf("javascript")>=0)&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var u,l,c,f=this;"function"==typeof t&&(t={success:t}),u=t.type||this.attr2("method"),l=t.url||this.attr2("action"),c="string"==typeof l?e.trim(l):"",c=c||window.location.href||"",c&&(c=(c.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:c,success:e.ajaxSettings.success,type:u||"GET",iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&t.beforeSerialize(this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var p=t.traditional;void 0===p&&(p=e.ajaxSettings.traditional);var d,h=[],v=this.formToArray(t.semantic,h);if(t.data&&(t.extraData=t.data,d=e.param(t.data,p)),t.beforeSubmit&&t.beforeSubmit(v,this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[v,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var g=e.param(v,p);d&&(g=g?g+"&"+d:d),"GET"==t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+g,t.data=null):t.data=g;var x=[];if(t.resetForm&&x.push(function(){f.resetForm()}),t.clearForm&&x.push(function(){f.clearForm(t.includeHidden)}),!t.dataType&&t.target){var b=t.success||function(){};x.push(function(r){var a=t.replaceTarget?"replaceWith":"html";e(t.target)[a](r).each(b,arguments)})}else t.success&&x.push(t.success);if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=x.length;o>i;i++)x[i].apply(n,[e,r,a||f,f])},t.error){var y=t.error;t.error=function(e,r,a){var n=t.context||this;y.apply(n,[e,r,a,f])}}if(t.complete){var T=t.complete;t.complete=function(e,r){var a=t.context||this;T.apply(a,[e,r,f])}}var j=e('input[type=file]:enabled[value!=""]',this),w=j.length>0,S="multipart/form-data",k=f.attr("enctype")==S||f.attr("encoding")==S,D=n.fileapi&&n.formdata;a("fileAPI :"+D);var A,E=(w||k)&&!D;t.iframe!==!1&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){A=s(v)}):A=s(v):A=(w||k)&&D?o(v):e.ajax(t),f.removeData("jqxhr").data("jqxhr",A);for(var L=0;h.length>L;L++)h[L]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n){if(n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var i={s:this.selector,c:this.context};return!e.isReady&&i.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(i.s,i.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().bind("submit.form-plugin",n,t).bind("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.unbind("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r){var a=[];if(0===this.length)return a;var i=this[0],o=t?i.getElementsByTagName("*"):i.elements;if(!o)return a;var s,u,l,c,f,m,p;for(s=0,m=o.length;m>s;s++)if(f=o[s],l=f.name,l&&!f.disabled)if(t&&i.clk&&"image"==f.type)i.clk==f&&(a.push({name:l,value:e(f).val(),type:f.type}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}));else if(c=e.fieldValue(f,!0),c&&c.constructor==Array)for(r&&r.push(f),u=0,p=c.length;p>u;u++)a.push({name:l,value:c[u]});else if(n.fileapi&&"file"==f.type){r&&r.push(f);var d=f.files;if(d.length)for(u=0;d.length>u;u++)a.push({name:l,value:d[u],type:f.type});else a.push({name:l,value:"",type:f.type})}else null!==c&&c!==void 0&&(r&&r.push(f),a.push({name:l,value:c,type:f.type,required:f.required}));if(!t&&i.clk){var h=e(i.clk),v=h[0];l=v.name,l&&!v.disabled&&"image"==v.type&&(a.push({name:l,value:h.val()}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}))}return a},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor==Array)for(var i=0,o=n.length;o>i;i++)r.push({name:a,value:n[i]});else null!==n&&n!==void 0&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;n>a;a++){var i=this[a],o=e.fieldValue(i,t);null===o||void 0===o||o.constructor==Array&&!o.length||(o.constructor==Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,n=t.type,i=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"==n||"button"==n||("checkbox"==n||"radio"==n)&&!t.checked||("submit"==n||"image"==n)&&t.form&&t.form.clk!=t||"select"==i&&-1==t.selectedIndex))return null;if("select"==i){var o=t.selectedIndex;if(0>o)return null;for(var s=[],u=t.options,l="select-one"==n,c=l?o+1:u.length,f=l?o:0;c>f;f++){var m=u[f];if(m.selected){var p=m.value;if(p||(p=m.attributes&&m.attributes.value&&!m.attributes.value.specified?m.text:m.value),l)return p;s.push(p)}}return s}return e(t).val()},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"==n?this.value="":"checkbox"==a||"radio"==a?this.checked=!1:"select"==n?this.selectedIndex=-1:"file"==a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(t===!0&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")})},e.fn.resetForm=function(){return this.each(function(){("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset()})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"==r||"radio"==r)this.checked=t;else if("option"==this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"==a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1})(jQuery);
          Evidence
          select
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        31. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bBUG\b and was detected in the element starting with: " // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane! ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (379 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 82920
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"82920-1230357900000"
          Last-Modified: Sat, 27 Dec 2008 06:05:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (82920 bytes)
          /*
           * jquery.layout 1.2.0
           *
           * Copyright (c) 2008 
           *   Fabrizio Balliano (http://www.fabrizioballiano.net)
           *   Kevin Dalman (http://allpro.net)
           *
           * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
           * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
           *
           * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
           * $Rev: 203 $
           * 
           * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
           */
          (function($) {
          
          $.fn.layout = function (opts) {
          
          /*
           * ###########################
           *   WIDGET CONFIG & OPTIONS
           * ###########################
           */
          
          	// DEFAULTS for options
          	var 
          		prefix = "ui-layout-" // prefix for ALL selectors and classNames
          	,	defaults = { //	misc default values
          			paneClass:				prefix+"pane"		// ui-layout-pane
          		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
          		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
          		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
          		,	buttonClass:			prefix+"button"		// ui-layout-button
          		,	contentSelector:		"."+prefix+"content"// ui-layout-content
          		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
          		}
          	;
          
          	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
          	var options = {
          		name:						""			// FUTURE REFERENCE - not used right now
          	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
          	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
          			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
          		,	closable:				true		// pane can open & close
          		,	resizable:				true		// when open, pane can be resized 
          		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
          		//,	paneSelector:			[ ]			// MUST be pane-specific!
          		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
          		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
          		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
          		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
          		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
          		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
          		,	resizerDragOpacity:		1			// option for ui.draggable
          		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
          		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
          		//,	size:					100			// inital size of pane - defaults are set 'per pane'
          		,	minSize:				0			// when manually resizing a pane
          		,	maxSize:				0			// ditto, 0 = no limit
          		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
          		,	spacing_closed:			6			// ditto - when pane is 'closed'
          		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
          		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
          		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
          		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
          		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
          		,	togglerTip_closed:		"Open"		// ditto
          		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
          		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
          		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
          		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
          		,	slideTrigger_close:		"mouseout"	// click, mouseout
          		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
          		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
          		,	togglerContent_closed:	""			// ditto
          		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
          		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
          		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
          		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
          		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
          		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
          		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
          		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
          		,	initClosed:				false		// true = init pane as 'closed'
          		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
          		
          		/*	callback options do not have to be set - listed here for reference only
          		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
          		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
          		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
          		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
          		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
          		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
          		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
          		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
          		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
          		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
          		*/
          		}
          	,	north: {
          			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
          		,	size:					"auto"
          		,	resizerCursor:			"n-resize"
          		}
          	,	south: {
          			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
          		,	size:					"auto"
          		,	resizerCursor:			"s-resize"
          		}
          	,	east: {
          			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
          		,	size:					200
          		,	resizerCursor:			"e-resize"
          		}
          	,	west: {
          			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
          		,	size:					200
          		,	resizerCursor:			"w-resize"
          		}
          	,	center: {
          			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
          		}
          
          	};
          
          
          	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
          		slide:	{
          			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	drop:	{
          			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	scale:	{
          			all:	{ duration:  "fast"	}
          		}
          	};
          
          
          	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
          	var config = {
          		allPanes:		"north,south,east,west,center"
          	,	borderPanes:	"north,south,east,west"
          	,	zIndex: { // set z-index values here
          			resizer_normal:	1		// normal z-index for resizer-bars
          		,	pane_normal:	2		// normal z-index for panes
          		,	mask:			4		// overlay div used to mask pane(s) during resizing
          		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
          		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
          		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
          		}
          	,	resizers: {
          			cssReq: {
          				position: 	"absolute"
          			,	padding: 	0
          			,	margin: 	0
          			,	fontSize:	"1px"
          			,	textAlign:	"left" // to counter-act "center" alignment!
          			,	overflow: 	"hidden" // keep toggler button from overflowing
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#DDD"
          			,	border:		"none"
          			}
          		}
          	,	togglers: {
          			cssReq: {
          				position: 	"absolute"
          			,	display: 	"block"
          			,	padding: 	0
          			,	margin: 	0
          			,	overflow:	"hidden"
          			,	textAlign:	"center"
          			,	fontSize:	"1px"
          			,	cursor: 	"pointer"
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#AAA"
          			}
          		}
          	,	content: {
          			cssReq: {
          				overflow:	"auto"
          			}
          		,	cssDef: {}
          		}
          	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
          			cssReq: {
          				position: 	"absolute"
          			,	margin:		0
          			,	zIndex: 	2
          			}
          		,	cssDef: {
          				padding:	"10px"
          			,	background:	"#FFF"
          			,	border:		"1px solid #BBB"
          			,	overflow:	"auto"
          			}
          		}
          	,	north: {
          			edge:			"top"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		0
          			,	bottom: 	"auto"
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	south: {
          			edge:			"bottom"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		"auto"
          			,	bottom: 	0
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	east: {
          			edge:			"right"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		"auto"
          			,	right: 		0
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	west: {
          			edge:			"left"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		0
          			,	right: 		"auto"
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	center: {
          			dir:			"center"
          		,	cssReq: {
          				left: 		"auto" // DYNAMIC
          			,	right: 		"auto" // DYNAMIC
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			,	width: 		"auto"
          			}
          		}
          	};
          
          
          	// DYNAMIC DATA
          	var state = {
          		// generate random 'ID#' to identify layout - used to create global namespace for timers
          		id:			Math.floor(Math.random() * 10000)
          	,	container:	{}
          	,	north:		{}
          	,	south:		{}
          	,	east:		{}
          	,	west:		{}
          	,	center:		{}
          	};
          
          
          	var 
          		altEdge = {
          			top:	"bottom"
          		,	bottom: "top"
          		,	left:	"right"
          		,	right:	"left"
          		}
          	,	altSide = {
          			north:	"south"
          		,	south:	"north"
          		,	east: 	"west"
          		,	west: 	"east"
          		}
          	;
          
          
          /*
           * ###########################
           *  INTERNAL HELPER FUNCTIONS
           * ###########################
           */
          
          	/**
          	 * isStr
          	 *
          	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
          	 */
          	var isStr = function (o) {
          		if (typeof o == "string")
          			return true;
          		else if (typeof o == "object") {
          			try {
          				var match = o.constructor.toString().match(/string/i); 
          				return (match !== null);
          			} catch (e) {} 
          		}
          		return false;
          	};
          
          	/**
          	 * str
          	 *
          	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
          	 *  else returns the original object
          	 */
          	var str = function (o) {
          		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
          		else return o;
          	};
          
          	/**
          	 * min / max
          	 *
          	 * Alias for Math.min/.max to simplify coding
          	 */
          	var min = function (x,y) { return Math.min(x,y); };
          	var max = function (x,y) { return Math.max(x,y); };
          
          	/**
          	 * transformData
          	 *
          	 * Processes the options passed in and transforms them into the format used by layout()
          	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
          	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
          	 * To update effects, options MUST use nested-keys format, with an effects key
          	 *
          	 * @callers  initOptions()
          	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
          	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
          	 */
          	var transformData = function (d) {
          		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
          		d = d || {};
          		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
          			json = $.extend( json, d ); // already in json format - add to base keys
          		else
          			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
          			$.each( d, function (key,val) {
          				a = key.split("__");
          				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
          			});
          		return json;
          	};
          
          	/**
          	 * setFlowCallback
          	 *
          	 * Set an INTERNAL callback to avoid simultaneous animation
          	 * Runs only if needed and only if all callbacks are not 'already set'!
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var setFlowCallback = function (action, pane, param) {
          		var
          			cb = action +","+ pane +","+ (param ? 1 : 0)
          		,	cP, cbPane
          		;
          		$.each(c.borderPanes.split(","), function (i,p) {
          			if (c[p].isMoving) {
          				bindCallback(p); // TRY to bind a callback
          				return false; // BREAK
          			}
          		});
          
          		function bindCallback (p, test) {
          			cP = c[p];
          			if (!cP.doCallback) {
          				cP.doCallback = true;
          				cP.callback = cb;
          			}
          			else { // try to 'chain' this callback
          				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
          				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
          					bindCallback (cpPane, true); // RECURSE
          			}
          		}
          	};
          
          	/**
          	 * execFlowCallback
          	 *
          	 * RUN the INTERNAL callback for this pane - if one exists
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var execFlowCallback = function (pane) {
          		var cP = c[pane];
          
          		// RESET flow-control flaGs
          		c.isLayoutBusy = false;
          		delete cP.isMoving;
          		if (!cP.doCallback || !cP.callback) return;
          
          		cP.doCallback = false; // RESET logic flag
          
          		// EXECUTE the callback
          		var
          			cb = cP.callback.split(",")
          		,	param = (cb[2] > 0 ? true : false)
          		;
          		if (cb[0] == "open")
          			open( cb[1], param  );
          		else if (cb[0] == "close")
          			close( cb[1], param );
          
          		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
          	};
          
          	/**
          	 * execUserCallback
          	 *
          	 * Executes a Callback function after a trigger event, like resize, open or close
          	 *
          	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
          	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
          	 */
          	var execUserCallback = function (pane, v_fn) {
          		if (!v_fn) return;
          		var fn;
          		try {
          			if (typeof v_fn == "function")
          				fn = v_fn;	
          			else if (typeof v_fn != "string")
          				return;
          			else if (v_fn.indexOf(",") > 0) {
          				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
          				var
          					args = v_fn.split(",")
          				,	fn = eval(args[0])
          				;
          				if (typeof fn=="function" && args.length > 1)
          					return fn(args[1]); // pass the argument parsed from 'list'
          			}
          			else // just the name of an external function?
          				fn = eval(v_fn);
          
          			if (typeof fn=="function")
          				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
          				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
          		}
          		catch (ex) {}
          	};
          
          	/**
          	 * cssNum
          	 *
          	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
          	 *
          	 * @callers  Called by many methods
          	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
          	 * @param String  property  The name of the CSS property, eg: top, width, etc.
          	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
          	 */
          	var cssNum = function ($E, prop) {
          		var
          			val = 0
          		,	hidden = false
          		,	visibility = ""
          		;
          		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
          			if ($.curCSS($E[0], "display", true) == "none") {
          				hidden = true;
          				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
          				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
          			}
          		}
          
          		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
          
          		if (hidden) { // WAS hidden, so put back the way it was
          			$E.css({ display: "none" });
          			if (visibility && visibility != "hidden")
          				$E.css({ visibility: visibility }); // reset 'visibility'
          		}
          
          		return val;
          	};
          
          	/**
          	 * cssW / cssH / cssSize
          	 *
          	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
          	 *
          	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
          	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
          	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
          	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
          	 *
          	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
          	 */
          	var cssW = function (e, outerWidth) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerWidth <= 0)
          			return 0;
          		else if (!(outerWidth>0))
          			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
          
          		if (!$.boxModel)
          			return outerWidth;
          
          		else // strip border and padding size from outerWidth to get CSS Width
          			return outerWidth
          				- cssNum($E, "paddingLeft")		
          				- cssNum($E, "paddingRight")
          				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
          				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
          			;
          	};
          	var cssH = function (e, outerHeight) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerHeight <= 0)
          			return 0;
          		else if (!(outerHeight>0))
          			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
          
          		if (!$.boxModel)
          			return outerHeight;
          
          		else // strip border and padding size from outerHeight to get CSS Height
          			return outerHeight
          				- cssNum($E, "paddingTop")
          				- cssNum($E, "paddingBottom")
          				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
          				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
          			;
          	};
          	var cssSize = function (pane, outerSize) {
          		if (c[pane].dir=="horz") // pane = north or south
          			return cssH(pane, outerSize);
          		else // pane = east or west
          			return cssW(pane, outerSize);
          	};
          
          	/**
          	 * getPaneSize
          	 *
          	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
          	 *
          	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
          	 */
          	var getPaneSize = function (pane, inclSpace) {
          		var 
          			$P	= $Ps[pane]
          		,	o	= options[pane]
          		,	s	= state[pane]
          		,	oSp	= (inclSpace ? o.spacing_open : 0)
          		,	cSp	= (inclSpace ? o.spacing_closed : 0)
          		;
          		if (!$P || s.isHidden)
          			return 0;
          		else if (s.isClosed || (s.isSliding && inclSpace))
          			return cSp;
          		else if (c[pane].dir == "horz")
          			return $P.outerHeight() + oSp;
          		else // dir == "vert"
          			return $P.outerWidth() + oSp;
          	};
          
          	var setPaneMinMaxSizes = function (pane) {
          		var 
          			d				= cDims
          		,	edge			= c[pane].edge
          		,	dir				= c[pane].dir
          		,	o				= options[pane]
          		,	s				= state[pane]
          		,	$P				= $Ps[pane]
          		,	$altPane		= $Ps[ altSide[pane] ]
          		,	paneSpacing		= o.spacing_open
          		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
          		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
          		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
          		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
          		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
          		,	minSize			= s.minSize || 0
          		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
          		,	minPos, maxPos	// used to set resizing limits
          		;
          		switch (pane) {
          			case "north":	minPos = d.offsetTop + minSize;
          							maxPos = d.offsetTop + maxSize;
          							break;
          			case "west":	minPos = d.offsetLeft + minSize;
          							maxPos = d.offsetLeft + maxSize;
          							break;
          			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
          							maxPos = d.offsetTop + d.innerHeight - minSize;
          							break;
          			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
          							maxPos = d.offsetLeft + d.innerWidth - minSize;
          							break;
          		}
          		// save data to pane-state
          		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
          	};
          
          	/**
          	 * getPaneDims
          	 *
          	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
          	 *
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
          	 */
          	var getPaneDims = function () {
          		var d = {
          			top:	getPaneSize("north", true) // true = include 'spacing' value for p
          		,	bottom:	getPaneSize("south", true)
          		,	left:	getPaneSize("west", true)
          		,	right:	getPaneSize("east", true)
          		,	width:	0
          		,	height:	0
          		};
          
          		with (d) {
          			width 	= cDims.innerWidth - left - right;
          			height 	= cDims.innerHeight - bottom - top;
          			// now add the 'container border/padding' to get final positions - relative to the container
          			top		+= cDims.top;
          			bottom	+= cDims.bottom;
          			left	+= cDims.left;
          			right	+= cDims.right;
          		}
          
          		return d;
          	};
          
          
          	/**
          	 * getElemDims
          	 *
          	 * Returns data for setting size of an element (container or a pane).
          	 *
          	 * @callers  create(), onWindowResize() for container, plus others for pane
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
          	 */
          	var getElemDims = function ($E) {
          		var
          			d = {} // dimensions hash
          		,	e, b, p // edge, border, padding
          		;
          
          		$.each("Left,Right,Top,Bottom".split(","), function () {
          			e = str(this);
          			b = d["border" +e] = cssNum($E, "border"+e+"Width");
          			p = d["padding"+e] = cssNum($E, "padding"+e);
          			d["offset" +e] = b + p; // total offset of content from outer edge
          			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
          			if ($E == $Container)
          				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
          		});
          
          		d.innerWidth  = d.outerWidth  = $E.outerWidth();
          		d.innerHeight = d.outerHeight = $E.outerHeight();
          		if ($.boxModel) {
          			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
          			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
          		}
          
          		return d;
          	};
          
          
          	var setTimer = function (pane, action, fn, ms) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) return; // timer already set!
          		else Timers[name] = setTimeout(fn, ms);
          	};
          
          	var clearTimer = function (pane, action) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) {
          			clearTimeout( Timers[name] );
          			delete Timers[name];
          			return true;
          		}
          		else
          			return false;
          	};
          
          
          /*
           * ###########################
           *   INITIALIZATION METHODS
           * ###########################
           */
          
          	/**
          	 * create
          	 *
          	 * Initialize the layout - called automatically whenever an instance of layout is created
          	 *
          	 * @callers  NEVER explicity called
          	 * @returns  An object pointer to the instance created
          	 */
          	var create = function () {
          		// initialize config/options
          		initOptions();
          
          		// initialize all objects
          		initContainer();	// set CSS as needed and init state.container dimensions
          		initPanes();		// size & position all panes
          		initHandles();		// create and position all resize bars & togglers buttons
          		initResizable();	// activate resizing on all panes where resizable=true
          		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
          
          		if (options.scrollToBookmarkOnLoad)
          			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
          
          		// bind hotkey function - keyDown - if required
          		initHotkeys();
          
          		// bind resizeAll() for 'this layout instance' to window.resize event
          		$(window).resize(function () {
          			var timerID = "timerLayout_"+state.id;
          			if (window[timerID]) clearTimeout(window[timerID]);
          			window[timerID] = null;
          			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
          				window[timerID] = setTimeout(resizeAll, 100);
          			else // most other browsers have a built-in delay before firing the resize event
          				resizeAll(); // resize all layout elements NOW!
          		});
          	};
          
          	/**
          	 * initContainer
          	 *
          	 * Validate and initialize container CSS and events
          	 *
          	 * @callers  create()
          	 */
          	var initContainer = function () {
          		try { // format html/body if this is a full page layout
          			if ($Container[0].tagName == "BODY") {
          				$("html").css({
          					height:		"100%"
          				,	overflow:	"hidden"
          				});
          				$("body").css({
          					position:	"relative"
          				,	height:		"100%"
          				,	overflow:	"hidden"
          				,	margin:		0
          				,	padding:	0		// TODO: test whether body-padding could be handled?
          				,	border:		"none"	// a body-border creates problems because it cannot be measured!
          				});
          			}
          			else { // set required CSS - overflow and position
          				var
          					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
          				,	p	= $Container.css("position")
          				,	h	= $Container.css("height")
          				;
          				// if this is a NESTED layout, then outer-pane ALREADY has position and height
          				if (!$Container.hasClass("ui-layout-pane")) {
          					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
          						CSS.position = "relative"; // container MUST have a 'position'
          					if (!h || h=="auto")
          						CSS.height = "100%"; // container MUST have a 'height'
          				}
          				$Container.css( CSS );
          			}
          		} catch (ex) {}
          
          		// get layout-container dimensions (updated when necessary)
          		cDims = state.container = getElemDims( $Container ); // update data-pointer too
          	};
          
          	/**
          	 * initHotkeys
          	 *
          	 * Bind layout hotkeys - if options enabled
          	 *
          	 * @callers  create()
          	 */
          	var initHotkeys = function () {
          		// bind keyDown to capture hotkeys, if option enabled for ANY pane
          		$.each(c.borderPanes.split(","), function (i,pane) {
          			var o = options[pane];
          			if (o.enableCursorHotkey || o.customHotkey) {
          				$(document).keydown( keyDown ); // only need to bind this ONCE
          				return false; // BREAK - binding was done
          			}
          		});
          	};
          
          	/**
          	 * initOptions
          	 *
          	 * Build final CONFIG and OPTIONS data
          	 *
          	 * @callers  create()
          	 */
          	var initOptions = function () {
          		// simplify logic by making sure passed 'opts' var has basic keys
          		opts = transformData( opts );
          
          		// update default effects, if case user passed key
          		if (opts.effects) {
          			$.extend( effects, opts.effects );
          			delete opts.effects;
          		}
          
          		// see if any 'global options' were specified
          		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
          			if (opts[key] !== undefined)
          				options[key] = opts[key];
          			else if (opts.defaults[key] !== undefined) {
          				options[key] = opts.defaults[key];
          				delete opts.defaults[key];
          			}
          		});
          
          		// remove any 'defaults' that MUST be set 'per-pane'
          		$.each("paneSelector,resizerCursor,customHotkey".split(","),
          			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
          		);
          
          		// now update options.defaults
          		$.extend( options.defaults, opts.defaults );
          		// make sure required sub-keys exist
          		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
          
          		// merge all config & options for the 'center' pane
          		c.center = $.extend( true, {}, c.defaults, c.center );
          		$.extend( options.center, opts.center );
          		// Most 'default options' do not apply to 'center', so add only those that DO
          		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
          		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
          			function (idx,key) { options.center[key] = o_Center[key]; }
          		);
          
          		var defs = options.defaults;
          
          		// create a COMPLETE set of options for EACH border-pane
          		$.each(c.borderPanes.split(","), function(i,pane) {
          			// apply 'pane-defaults' to CONFIG.PANE
          			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
          			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
          			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
          
          			// make sure we have base-classes
          			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
          			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
          			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
          
          			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
          			$.each(["_open","_close",""], function (i,n) { 
          				var
          					sName		= "fxName"+n
          				,	sSpeed		= "fxSpeed"+n
          				,	sSettings	= "fxSettings"+n
          				;
          				// recalculate fxName according to specificity rules
          				o[sName] =
          					opts[pane][sName]		// opts.west.fxName_open
          				||	opts[pane].fxName		// opts.west.fxName
          				||	opts.defaults[sName]	// opts.defaults.fxName_open
          				||	opts.defaults.fxName	// opts.defaults.fxName
          				||	o[sName]				// options.west.fxName_open
          				||	o.fxName				// options.west.fxName
          				||	defs[sName]				// options.defaults.fxName_open
          				||	defs.fxName				// options.defaults.fxName
          				||	"none"
          				;
          				// validate fxName to be sure is a valid effect
          				var fxName = o[sName];
          				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
          					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
          				// set vars for effects subkeys to simplify logic
          				var
          					fx = effects[fxName]	|| {} // effects.slide
          				,	fx_all	= fx.all		|| {} // effects.slide.all
          				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
          				;
          				// RECREATE the fxSettings[_open|_close] keys using specificity rules
          				o[sSettings] = $.extend(
          					{}
          				,	fx_all						// effects.slide.all
          				,	fx_pane						// effects.slide.west
          				,	defs.fxSettings || {}		// options.defaults.fxSettings
          				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
          				,	o.fxSettings				// options.west.fxSettings
          				,	o[sSettings]				// options.west.fxSettings_open
          				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
          				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
          				,	opts[pane].fxSettings		// opts.west.fxSettings
          				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
          				);
          				// recalculate fxSpeed according to specificity rules
          				o[sSpeed] =
          					opts[pane][sSpeed]		// opts.west.fxSpeed_open
          				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
          				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
          				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
          				||	o[sSpeed]				// options.west.fxSpeed_open
          				||	o[sSettings].duration	// options.west.fxSettings_open.duration
          				||	o.fxSpeed				// options.west.fxSpeed
          				||	o.fxSettings.duration	// options.west.fxSettings.duration
          				||	defs.fxSpeed			// options.defaults.fxSpeed
          				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
          				||	fx_pane.duration		// effects.slide.west.duration
          				||	fx_all.duration			// effects.slide.all.duration
          				||	"normal"				// DEFAULT
          				;
          				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
          			});
          		});
          	};
          
          	/**
          	 * initPanes
          	 *
          	 * Initialize module objects, styling, size and position for all panes
          	 *
          	 * @callers  create()
          	 */
          	var initPanes = function () {
          		// NOTE: do north & south FIRST so we can measure their height - do center LAST
          		$.each(c.allPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	fx		= s.fx
          			,	dir		= c[pane].dir
          			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
          			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
          			,	minSize	= o.minSize || 1
          			,	maxSize	= o.maxSize || 9999
          			,	spacing	= o.spacing_open || 0
          			,	sel		= o.paneSelector
          			,	isIE6	= ($.browser.msie && $.browser.version < 7)
          			,	CSS		= {}
          			,	$P, $C
          			;
          			$Cs[pane] = false; // init
          
          			if (sel.substr(0,1)==="#") // ID selector
          				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
          				$P = $Ps[pane] = $Container.find(sel+":first");
          			else { // class or other selector
          				$P = $Ps[pane] = $Container.children(sel+":first");
          				// look for the pane nested inside a 'form' element
          				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
          			}
          
          			if (!$P.length) {
          				$Ps[pane] = false; // logic
          				return true; // SKIP to next
          			}
          
          			// add basic classes & attributes
          			$P
          				.attr("pane", pane) // add pane-identifier
          				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
          			;
          
          			// init pane-logic vars, etc.
          			if (pane != "center") {
          				s.isClosed  = false; // true = pane is closed
          				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
          				s.isResizing= false; // true = pane is in process of being resized
          				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
          				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
          				// create special keys for internal use
          				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
          			}
          
          			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
          			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
          			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
          			CSS = {};	// reset var
          
          			// set css-position to account for container borders & padding
          			switch (pane) {
          				case "north": 	CSS.top 	= cDims.top;
          								CSS.left 	= cDims.left;
          								CSS.right	= cDims.right;
          								break;
          				case "south": 	CSS.bottom	= cDims.bottom;
          								CSS.left 	= cDims.left;
          								CSS.right 	= cDims.right;
          								break;
          				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
          								break;
          				case "east": 	CSS.right 	= cDims.right; // ditto
          								break;
          				case "center":	// top, left, width & height set by sizeMidPanes()
          			}
          
          			if (dir == "horz") { // north or south pane
          				if (size === 0 || size == "auto") {
          					$P.css({ height: "auto" });
          					size = $P.outerHeight();
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerHeight - spacing);
          				CSS.height = max(1, cssH(pane, size));
          				s.size = size; // update state
          				// make sure minSize is sufficient to avoid errors
          				s.maxSize = maxSize; // init value
          				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
          				// handle IE6
          				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
          				$P.css(CSS); // apply size & position
          			}
          			else if (dir == "vert") { // east or west pane
          				if (size === 0 || size == "auto") {
          					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
          					size = $P.outerWidth();
          					$P.css({ float: "none" }); // RESET
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerWidth - spacing);
          				CSS.width = max(1, cssW(pane, size));
          				s.size = size; // update state
          				s.maxSize = maxSize; // init value
          				// make sure minSize is sufficient to avoid errors
          				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
          				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
          				sizeMidPanes(pane, null, true); // true = onInit
          			}
          			else if (pane == "center") {
          				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
          				sizeMidPanes("center", null, true); // true = onInit
          			}
          
          			// close or hide the pane if specified in settings
          			if (o.initClosed && o.closable) {
          				$P.hide().addClass("closed");
          				s.isClosed = true;
          			}
          			else if (o.initHidden || o.initClosed) {
          				hide(pane, true); // will be completely invisible - no resizer or spacing
          				s.isHidden = true;
          			}
          			else
          				$P.addClass("open");
          
          			// check option for auto-handling of pop-ups & drop-downs
          			if (o.showOverflowOnHover)
          				$P.hover( allowOverflow, resetOverflow );
          
          			/*
          			 *	see if this pane has a 'content element' that we need to auto-size
          			 */
          			if (o.contentSelector) {
          				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
          				if (!$C.length) {
          					$Cs[pane] = false;
          					return true; // SKIP to next
          				}
          				$C.css( c.content.cssReq );
          				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
          				// NO PANE-SCROLLING when there is a content-div
          				$P.css({ overflow: "hidden" });
          			}
          		});
          	};
          
          	/**
          	 * initHandles
          	 *
          	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
          	 *
          	 * @callers  create()
          	 */
          	var initHandles = function () {
          		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	rClass	= o.resizerClass
          			,	tClass	= o.togglerClass
          			,	$P		= $Ps[pane]
          			;
          			$Rs[pane] = false; // INIT
          			$Ts[pane] = false;
          
          			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
          
          			var 
          				edge	= c[pane].edge
          			,	isOpen	= $P.is(":visible")
          			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
          			,	_pane	= "-"+ pane // used for classNames
          			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
          			,	$R, $T
          			;
          			// INIT RESIZER BAR
          			$R = $Rs[pane] = $("<span></span>");
          	
          			if (isOpen && o.resizable)
          				; // this is handled by initResizable
          			else if (!isOpen && o.slidable)
          				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
          	
          			$R
          				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
          				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
          				.attr("resizer", pane) // so we can read this from the resizer
          				.css(c.resizers.cssReq) // add base/required styles
          				// POSITION of resizer bar - allow for container border & padding
          				.css(edge, cDims[edge] + getPaneSize(pane))
          				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
          				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
          				.appendTo($Container) // append DIV to container
          			;
          			 // ADD VISUAL STYLES
          			if (o.applyDefaultStyles)
          				$R.css(c.resizers.cssDef);
          
          			if (o.closable) {
          				// INIT COLLAPSER BUTTON
          				$T = $Ts[pane] = $("<div></div>");
          				$T
          					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
          					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
          					.css(c.togglers.cssReq) // add base/required styles
          					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
          					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
          					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
          					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
          					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
          					.appendTo($R) // append SPAN to resizer DIV
          				;
          
          				// ADD INNER-SPANS TO TOGGLER
          				if (o.togglerContent_open) // ui-layout-open
          					$("<span>"+ o.togglerContent_open +"</span>")
          						.addClass("content content-open")
          						.css("display", s.isClosed ? "none" : "block")
          						.appendTo( $T )
          					;
          				if (o.togglerContent_closed) // ui-layout-closed
          					$("<span>"+ o.togglerContent_closed +"</span>")
          						.addClass("content content-closed")
          						.css("display", s.isClosed ? "block" : "none")
          						.appendTo( $T )
          					;
          
          				 // ADD BASIC VISUAL STYLES
          				if (o.applyDefaultStyles)
          					$T.css(c.togglers.cssDef);
          
          				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          			}
          
          		});
          
          		// SET ALL HANDLE SIZES & LENGTHS
          		sizeHandles("all", true); // true = onInit
          	};
          
          	/**
          	 * initResizable
          	 *
          	 * Add resize-bars to all panes that specify it in options
          	 *
          	 * @dependancies  $.fn.resizable - will abort if not found
          	 * @callers  create()
          	 */
          	var initResizable = function () {
          		var
          			draggingAvailable = (typeof $.fn.draggable == "function")
          		,	minPosition, maxPosition, edge // set in start()
          		;
          
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			;
          			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
          				o.resizable = false;
          				return true; // skip to next
          			}
          
          			var 
          				rClass				= o.resizerClass
          			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
          			,	dragClass			= rClass+"-drag"			// resizer-drag
          			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
          			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
          			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
          			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
          			,	draggingClassSet	= false 					// logic var
          			,	$P 					= $Ps[pane]
          			,	$R					= $Rs[pane]
          			;
          
          			if (!s.isClosed)
          				$R
          					.attr("title", o.resizerTip)
          					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
          				;
          
          			$R.draggable({
          				containment:	$Container[0] // limit resizing to layout container
          			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
          			,	delay:			200
          			,	distance:		1
          			//	basic format for helper - style it using class: .ui-draggable-dragging
          			,	helper:			"clone"
          			,	opacity:		o.resizerDragOpacity
          			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
          			,	zIndex:			c.zIndex.resizing
          
          			,	start: function (e, ui) {
          					// onresize_start callback - will CANCEL hide if returns false
          					// TODO: CONFIRM that dragging can be cancelled like this???
          					if (false === execUserCallback(pane, o.onresize_start)) return false;
          
          					s.isResizing = true; // prevent pane from closing while resizing
          					clearTimer(pane, "closeSlider"); // just in case already triggered
          
          					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
          					draggingClassSet = false; // reset logic var - see drag()
          
          					// SET RESIZING LIMITS - used in drag()
          					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
          					setPaneMinMaxSizes(pane); // update pane-state
          					s.minPosition -= resizerWidth;
          					s.maxPosition -= resizerWidth;
          					edge = (c[pane].dir=="horz" ? "top" : "left");
          
          					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
          					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
          						$('<div class="ui-layout-mask"/>')
          							.css({
          								background:	"#fff"
          							,	opacity:	"0.001"
          							,	zIndex:		9
          							,	position:	"absolute"
          							,	width:		this.offsetWidth+"px"
          							,	height:		this.offsetHeight+"px"
          							})
          							.css($(this).offset()) // top & left
          							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
          						;
          					});
          				}
          
          			,	drag: function (e, ui) {
          					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
          						$(".ui-draggable-dragging")
          							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
          							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
          						;
          						draggingClassSet = true;
          						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
          						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
          					}
          					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
          					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
          					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
          				}
          
          			,	stop: function (e, ui) {
          					var 
          						dragPos	= ui.position
          					,	resizerPos
          					,	newSize
          					;
          					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
          	
          					switch (pane) {
          						case "north":	resizerPos = dragPos.top; break;
          						case "west":	resizerPos = dragPos.left; break;
          						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
          						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
          					}
          					// remove container margin from resizer position to get the pane size
          					newSize = resizerPos - cDims[ c[pane].edge ];
          
          					sizePane(pane, newSize);
          
          					// UN-MASK PANES MASKED IN drag.start
          					$("div.ui-layout-mask").remove(); // Remove iframe masks	
          
          					s.isResizing = false;
          				}
          
          			});
          		});
          	};
          
          
          
          /*
           * ###########################
           *       ACTION METHODS
           * ###########################
           */
          
          	/**
          	 * hide / show
          	 *
          	 * Completely 'hides' a pane, including its spacing - as if it does not exist
          	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
          	 *
          	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
          	 */
          	var hide = function (pane, onInit) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onhide_start)) return;
          
          		s.isSliding = false; // just in case
          
          		// now hide the elements
          		if ($R) $R.hide(); // hide resizer-bar
          		if (onInit || s.isClosed) {
          			s.isClosed = true; // to trigger open-animation on show()
          			s.isHidden  = true;
          			$P.hide(); // no animation when loading page
          			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          			execUserCallback(pane, o.onhide_end || o.onhide);
          		}
          		else {
          			s.isHiding = true; // used by onclose
          			close(pane, false); // adjust all panes to fit
          			//s.isHidden  = true; - will be set by close - if not cancelled
          		}
          	};
          
          	var show = function (pane, openPane) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onshow_start)) return;
          
          		s.isSliding = false; // just in case
          		s.isShowing = true; // used by onopen/onclose
          		//s.isHidden  = false; - will be set by open/close - if not cancelled
          
          		// now show the elements
          		if ($R && o.spacing_open > 0) $R.show();
          		if (openPane === false)
          			close(pane, true); // true = force
          		else
          			open(pane); // adjust all panes to fit
          	};
          
          
          	/**
          	 * toggle
          	 *
          	 * Toggles a pane open/closed by calling either open or close
          	 *
          	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
          	 */
          	var toggle = function (pane) {
          		var s = state[pane];
          		if (s.isHidden)
          			show(pane); // will call 'open' after unhiding it
          		else if (s.isClosed)
          			open(pane);
          		else
          			close(pane);
          	};
          
          	/**
          	 * close
          	 *
          	 * Close the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being closed, ie: north, south, east, or west
          	 */
          	var close = function (pane, force, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_sliding= "-sliding"
          		,	_closed	= "-closed"
          		// 	transfer logic vars to temp vars
          		,	isShowing = s.isShowing
          		,	isHiding = s.isHiding
          		;
          		// now clear the logic vars
          		delete s.isShowing;
          		delete s.isHiding;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!force && s.isClosed && !isShowing) return; // already closed
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("close", pane, force); // set a callback for this action, if possible
          			return; // ABORT 
          		}
          
          		// onclose_start callback - will CANCEL hide if returns false
          		// SKIP if just 'showing' a hidden pane as 'closed'
          		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		s.isClosed = true;
          		// update isHidden BEFORE sizing panes
          		if (isHiding) s.isHidden = true;
          		else if (isShowing) s.isHidden = false;
          
          		// sync any 'pin buttons'
          		syncPinBtns(pane, false);
          
          		// resize panes adjacent to this one
          		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          
          		// if this pane has a resizer bar, move it now
          		if ($R) {
          			$R
          				.css(edge, cDims[edge]) // move the resizer bar
          				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
          				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
          				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
          			;
          			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
          			if (o.resizable)
          				$R
          					.draggable("disable")
          					.css("cursor", "default")
          					.attr("title","")
          				;
          			// if pane has a toggler button, adjust that too
          			if ($T) {
          				$T
          					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
          					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
          					.attr("title", o.togglerTip_closed) // may be blank
          				;
          			}
          			sizeHandles(); // resize 'length' and position togglers for adjacent panes
          		}
          
          		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
          		if (doFX) {
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
          				lockPaneForFX(pane, false); // undo
          				if (!s.isClosed) return; // pane was opened before animation finished!
          				close_2();
          			});
          		}
          		else {
          			$P.hide(); // just hide pane NOW
          			close_2();
          		}
          
          		// SUBROUTINE
          		function close_2 () {
          			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          
          			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
          			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
          			// onhide OR onshow callback
          			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
          			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          
          	/**
          	 * open
          	 *
          	 * Open the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being opened, ie: north, south, east, or west
          	 */
          	var open = function (pane, slide, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_closed	= "-closed"
          		,	_sliding= "-sliding"
          		// 	transfer logic var to temp var
          		,	isShowing = s.isShowing
          		;
          		// now clear the logic var
          		delete s.isShowing;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!s.isClosed && !s.isSliding) return; // already open
          
          		// pane can ALSO be unhidden by just calling show(), so handle this scenario
          		if (s.isHidden && !isShowing) {
          			show(pane, true);
          			return;
          		}
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
          			return; // ABORT
          		}
          
          		// onopen_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onopen_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		// 'PIN PANE' - stop sliding
          		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
          			bindStopSlidingEvents(pane, false); // will set isSliding=false
          
          		s.isClosed = false;
          		// update isHidden BEFORE sizing panes
          		if (isShowing) s.isHidden = false;
          
          		// Container size may have changed - shrink the pane if now 'too big'
          		setPaneMinMaxSizes(pane); // update pane-state
          		if (s.size > s.maxSize) // pane is too big! resize it before opening
          			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
          
          		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
          
          		if (doFX) { // ANIMATE
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
          				lockPaneForFX(pane, false); // undo
          				if (s.isClosed) return; // pane was closed before animation finished!
          				open_2(); // continue
          			});
          		}
          		else {// no animation
          			$P.show();	// just show pane and...
          			open_2();	// continue
          		}
          
          		// SUBROUTINE
          		function open_2 () {
          			// NOTE: if isSliding, then other panes are NOT 'resized'
          			if (!s.isSliding) // resize all panes adjacent to this one
          				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
          
          			// if this pane has a toggler, move it now
          			if ($R) {
          				$R
          					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
          					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
          					.addClass( rClass+_open +" "+ rClass+_pane+_open )
          					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
          				;
          				if (o.resizable)
          					$R
          						.draggable("enable")
          						.css("cursor", o.resizerCursor)
          						.attr("title", o.resizerTip)
          					;
          				else
          					$R.css("cursor", "default"); // n-resize, s-resize, etc
          				// if pane also has a toggler button, adjust that too
          				if ($T) {
          					$T
          						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
          						.addClass( tClass+_open +" "+ tClass+_pane+_open )
          						.attr("title", o.togglerTip_open) // may be blank
          					;
          				}
          				sizeHandles("all"); // resize resizer & toggler sizes for all panes
          			}
          
          			// resize content every time pane opens - to be sure
          			sizeContent(pane);
          
          			// sync any 'pin buttons'
          			syncPinBtns(pane, !s.isSliding);
          
          			// onopen callback
          			execUserCallback(pane, o.onopen_end || o.onopen);
          
          			// onshow callback
          			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          	
          
          	/**
          	 * lockPaneForFX
          	 *
          	 * Must set left/top on East/South panes so animation will work properly
          	 *
          	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
          	 * @param Boolean  doLock  true = set left/top, false = remove
          	 */
          	var lockPaneForFX = function (pane, doLock) {
          		var $P = $Ps[pane];
          		if (doLock) {
          			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
          			if (pane=="south")
          				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
          			else if (pane=="east")
          				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
          		}
          		else {
          			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
          			if (pane=="south")
          				$P.css({ top: "auto" });
          			else if (pane=="east")
          				$P.css({ left: "auto" });
          		}
          	};
          
          
          	/**
          	 * bindStartSlidingEvent
          	 *
          	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
          	 *
          	 * @callers  open(), close()
          	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
          	 * @param Boolean  enable  Enable or Disable sliding?
          	 */
          	var bindStartSlidingEvent = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	$R		= $Rs[pane]
          		,	trigger	= o.slideTrigger_open
          		;
          		if (!$R || !o.slidable) return;
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
          		$R
          			// add or remove trigger event
          			[enable ? "bind" : "unbind"](trigger, slideOpen)
          			// set the appropriate cursor & title/tip
          			.css("cursor", (enable ? o.sliderCursor: "default"))
          			.attr("title", (enable ? o.sliderTip : ""))
          		;
          	};
          
          	/**
          	 * bindStopSlidingEvents
          	 *
          	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
          	 * Also increases zIndex when pane is sliding open
          	 * See bindStartSlidingEvent for code to control 'slide open'
          	 *
          	 * @callers  slideOpen(), slideClosed()
          	 * @param String  pane  The pane to process, 'north', 'south', etc.
          	 * @param Boolean  isOpen  Is pane open or closed?
          	 */
          	var bindStopSlidingEvents = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	s		= state[pane]
          		,	trigger	= o.slideTrigger_close
          		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          
          		s.isSliding = enable; // logic
          		clearTimer(pane, "closeSlider"); // just in case
          
          		// raise z-index when sliding
          		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
          		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
          
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
          
          		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
          		if (enable) { // BIND trigger events
          			$P.bind(trigger, slideClosed );
          			$R.bind(trigger, slideClosed );
          			if (trigger = "mouseout") {
          				$P.bind("mouseover", cancelMouseOut );
          				$R.bind("mouseover", cancelMouseOut );
          			}
          		}
          		else { // UNBIND trigger events
          			// TODO: why does unbind of a 'single function' not work reliably?
          			//$P[action](trigger, slideClosed );
          			$P.unbind(trigger);
          			$R.unbind(trigger);
          			if (trigger = "mouseout") {
          				//$P[action]("mouseover", cancelMouseOut );
          				$P.unbind("mouseover");
          				$R.unbind("mouseover");
          				clearTimer(pane, "closeSlider");
          			}
          		}
          
          		// SUBROUTINE for mouseout timer clearing
          		function cancelMouseOut (evt) {
          			clearTimer(pane, "closeSlider");
          			evt.stopPropagation();
          		}
          	};
          
          	var slideOpen = function () {
          		var pane = $(this).attr("resizer"); // attr added by initHandles
          		if (state[pane].isClosed) { // skip if already open!
          			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
          			open(pane, true); // true = slide - ie, called from here!
          		}
          	};
          
          	var slideClosed = function () {
          		var
          			$E = $(this)
          		,	pane = $E.attr("pane") || $E.attr("resizer")
          		,	o = options[pane]
          		,	s = state[pane]
          		;
          		if (s.isClosed || s.isResizing)
          			return; // skip if already closed OR in process of resizing
          		else if (o.slideTrigger_close == "click")
          			close_NOW(); // close immediately onClick
          		else // trigger = mouseout - use a delay
          			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
          
          		// SUBROUTINE for timed close
          		function close_NOW () {
          			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
          			if (!s.isClosed) close(pane); // skip if already closed!
          		}
          	};
          
          
          	/**
          	 * sizePane
          	 *
          	 * @callers  initResizable.stop()
          	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
          	 * @param Integer  newSize  The new size for this pane - will be validated
          	 */
          	var sizePane = function (pane, size) {
          		// TODO: accept "auto" as size, and size-to-fit pane content
          		var 
          			edge	= c[pane].edge
          		,	dir		= c[pane].dir
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          		// calculate 'current' min/max sizes
          		setPaneMinMaxSizes(pane); // update pane-state
          		// compare/update calculated min/max to user-options
          		s.minSize = max(s.minSize, o.minSize);
          		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
          		// validate passed size
          		size = max(size, s.minSize);
          		size = min(size, s.maxSize);
          		s.size = size; // update state
          
          		// move the resizer bar and resize the pane
          		$R.css( edge, size + cDims[edge] );
          		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
          
          		// resize all the adjacent panes, and adjust their toggler buttons
          		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
          		sizeHandles();
          		sizeContent(pane);
          		execUserCallback(pane, o.onresize_end || o.onresize);
          	};
          
          	/**
          	 * sizeMidPanes
          	 *
          	 * @callers  create(), open(), close(), onWindowResize()
          	 */
          	var sizeMidPanes = function (panes, overrideDims, onInit) {
          		if (!panes || panes == "all") panes = "east,west,center";
          
          		var d = getPaneDims();
          		if (overrideDims) $.extend( d, overrideDims );
          
          		$.each(panes.split(","), function() {
          			if (!$Ps[this]) return; // NO PANE - skip
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	hasRoom	= true
          			,	CSS		= {}
          			;
          
          			if (pane == "center") {
          				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
          				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
          				CSS.width  = max(1, cssW(pane, CSS.width));
          				CSS.height = max(1, cssH(pane, CSS.height));
          				hasRoom = (CSS.width > 1 && CSS.height > 1);
          				/*
          				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
          				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
          				 */
          				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
          					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
          					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
          				}
          			}
          			else { // for east and west, set only the height
          				CSS.top = d.top;
          				CSS.bottom = d.bottom;
          				CSS.height = max(1, cssH(pane, d.height));
          				hasRoom = (CSS.height > 1);
          			}
          
          			if (hasRoom) {
          				$P.css(CSS);
          				if (s.noRoom) {
          					s.noRoom = false;
          					if (s.isHidden) return;
          					else show(pane, !s.isClosed);
          					/* OLD CODE - keep until sure line above works right!
          					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
          					if ($R) $R.show();
          					*/
          				}
          				if (!onInit) {
          					sizeContent(pane);
          					execUserCallback(pane, o.onresize_end || o.onresize);
          				}
          			}
          			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
          				s.noRoom = true; // update state
          				if (s.isHidden) return;
          				if (onInit) { // skip onhide callback and other logic onLoad
          					$P.hide();
          					if ($R) $R.hide();
          				}
          				else hide(pane);
          			}
          		});
          	};
          
          
          	var sizeContent = function (panes) {
          		if (!panes || panes == "all") panes = c.allPanes;
          
          		$.each(panes.split(","), function() {
          			if (!$Cs[this]) return; // NO CONTENT - skip
          			var 
          				pane	= str(this)
          			,	ignore	= options[pane].contentIgnoreSelector
          			,	$P		= $Ps[pane]
          			,	$C		= $Cs[pane]
          			,	e_C		= $C[0]		// DOM element
          			,	height	= cssH($P);	// init to pane.innerHeight
          			;
          			$P.children().each(function() {
          				if (this == e_C) return; // Content elem - skip
          				var $E = $(this);
          				if (!ignore || !$E.is(ignore))
          					height -= $E.outerHeight();
          			});
          			if (height > 0)
          				height = cssH($C, height);
          			if (height < 1)
          				$C.hide(); // no room for content!
          			else
          				$C.css({ height: height }).show();
          		});
          	};
          
          
          	/**
          	 * sizeHandles
          	 *
          	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
          	 *
          	 * @callers  initHandles(), open(), close(), resizeAll()
          	 */
          	var sizeHandles = function (panes, onInit) {
          		if (!panes || panes == "all") panes = c.borderPanes;
          
          		$.each(panes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	$T		= $Ts[pane]
          			;
          			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
          
          			var 
          				dir			= c[pane].dir
          			,	_state		= (s.isClosed ? "_closed" : "_open")
          			,	spacing		= o["spacing"+ _state]
          			,	togAlign	= o["togglerAlign"+ _state]
          			,	togLen		= o["togglerLength"+ _state]
          			,	paneLen
          			,	offset
          			,	CSS = {}
          			;
          			if (spacing == 0) {
          				$R.hide();
          				return;
          			}
          			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
          				$R.show(); // in case was previously hidden
          
          			// Resizer Bar is ALWAYS same width/height of pane it is attached to
          			if (dir == "horz") { // north/south
          				paneLen = $P.outerWidth();
          				$R.css({
          					width:	max(1, cssW($R, paneLen)) // account for borders & padding
          				,	height:	max(1, cssH($R, spacing)) // ditto
          				,	left:	cssNum($P, "left")
          				});
          			}
          			else { // east/west
          				paneLen = $P.outerHeight();
          				$R.css({
          					height:	max(1, cssH($R, paneLen)) // account for borders & padding
          				,	width:	max(1, cssW($R, spacing)) // ditto
          				,	top:	cDims.top + getPaneSize("north", true)
          				//,	top:	cssNum($Ps["center"], "top")
          				});
          				
          			}
          
          			if ($T) {
          				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
          					$T.hide(); // always HIDE the toggler when 'sliding'
          					return;
          				}
          				else
          					$T.show(); // in case was previously hidden
          
          				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
          					togLen = paneLen;
          					offset = 0;
          				}
          				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
          					if (typeof togAlign == "string") {
          						switch (togAlign) {
          							case "top":
          							case "left":	offset = 0;
          											break;
          							case "bottom":
          							case "right":	offset = paneLen - togLen;
          											break;
          							case "middle":
          							case "center":
          							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
          						}
          					}
          					else { // togAlign = number
          						var x = parseInt(togAlign); //
          						if (togAlign >= 0) offset = x;
          						else offset = paneLen - togLen + x; // NOTE: x is negative!
          					}
          				}
          
          				var
          					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
          				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
          				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
          				;
          				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
          				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
          
          				if (dir == "horz") { // north/south
          					var width = cssW($T, togLen);
          					$T.css({
          						width:	max(0, width)  // account for borders & padding
          					,	height:	max(1, cssH($T, spacing)) // ditto
          					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
          				}
          				else { // east/west
          					var height = cssH($T, togLen);
          					$T.css({
          						height:	max(0, height)  // account for borders & padding
          					,	width:	max(1, cssW($T, spacing)) // ditto
          					,	top:	offset // POSITION the toggler
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
          				}
          
          
          			}
          
          			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
          			if (onInit && o.initHidden) {
          				$R.hide();
          				if ($T) $T.hide();
          			}
          		});
          	};
          
          
          	/**
          	 * resizeAll
          	 *
          	 * @callers  window.onresize(), callbacks or custom code
          	 */
          	var resizeAll = function () {
          		var
          			oldW	= cDims.innerWidth
          		,	oldH	= cDims.innerHeight
          		;
          		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
          
          		var
          			checkH	= (cDims.innerHeight < oldH)
          		,	checkW	= (cDims.innerWidth < oldW)
          		,	s, dir
          		;
          
          		if (checkH || checkW)
          			// NOTE special order for sizing: S-N-E-W
          			$.each(["south","north","east","west"], function(i,pane) {
          				s = state[pane];
          				dir = c[pane].dir;
          				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
          					setPaneMinMaxSizes(pane); // update pane-state
          					// shrink pane if 'too big' to fit
          					if (s.size > s.maxSize)
          						sizePane(pane, s.maxSize);
          				}
          			});
          
          		sizeMidPanes("all");
          		sizeHandles("all"); // reposition the toggler elements
          	};
          
          
          	/**
          	 * keyDown
          	 *
          	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
          	 *
          	 * @callers  document.keydown()
          	 */
          	function keyDown (evt) {
          		if (!evt) return true;
          		var code = evt.keyCode;
          		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
          
          		var
          			PANE = {
          				38: "north" // Up Cursor
          			,	40: "south" // Down Cursor
          			,	37: "west"  // Left Cursor
          			,	39: "east"  // Right Cursor
          			}
          		,	isCursorKey = (code >= 37 && code <= 40)
          		,	ALT = evt.altKey // no worky!
          		,	SHIFT = evt.shiftKey
          		,	CTRL = evt.ctrlKey
          		,	pane = false
          		,	s, o, k, m, el
          		;
          
          		if (!CTRL && !SHIFT)
          			return true; // no modifier key - abort
          		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
          			pane = PANE[code];
          		else // check to see if this matches a custom-hotkey
          			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
          				o = options[p];
          				k = o.customHotkey;
          				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
          				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
          					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
          						pane = p;
          						return false; // BREAK
          					}
          				}
          			});
          
          		if (!pane) return true; // no hotkey - abort
          
          		// validate pane
          		o = options[pane]; // get pane options
          		s = state[pane]; // get pane options
          		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
          
          		// see if user is in a 'form field' because may be 'selecting text'!
          		el = evt.target || evt.srcElement;
          		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
          			return true; // allow text-selection
          
          		// SYNTAX NOTES
          		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
          		// use "return false" to abort keystroke AND abort function
          		toggle(pane);
          		evt.stopPropagation();
          		evt.returnValue = false; // CANCEL key
          		return false;
          	};
          
          
          /*
           * ###########################
           *     UTILITY METHODS
           *   called externally only
           * ###########################
           */
          
          	function allowOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).attr("pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		;
          
          		// if pane is already raised, then reset it before doing it again!
          		// this would happen if allowOverflow is attached to BOTH the pane and an element 
          		if (s.cssSaved)
          			resetOverflow(pane); // reset previous CSS before continuing
          
          		// if pane is raised by sliding or resizing, or it's closed, then abort
          		if (s.isSliding || s.isResizing || s.isClosed) {
          			s.cssSaved = false;
          			return;
          		}
          
          		var
          			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
          		,	curCSS	= {}
          		,	of		= $P.css("overflow")
          		,	ofX		= $P.css("overflowX")
          		,	ofY		= $P.css("overflowY")
          		;
          		// determine which, if any, overflow settings need to be changed
          		if (of != "visible") {
          			curCSS.overflow = of;
          			newCSS.overflow = "visible";
          		}
          		if (ofX && ofX != "visible" && ofX != "auto") {
          			curCSS.overflowX = ofX;
          			newCSS.overflowX = "visible";
          		}
          		if (ofY && ofY != "visible" && ofY != "auto") {
          			curCSS.overflowY = ofX;
          			newCSS.overflowY = "visible";
          		}
          
          		// save the current overflow settings - even if blank!
          		s.cssSaved = curCSS;
          
          		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
          		$P.css( newCSS );
          
          		// make sure the zIndex of all other panes is normal
          		$.each(c.allPanes.split(","), function(i, p) {
          			if (p != pane) resetOverflow(p);
          		});
          
          	};
          
          	function resetOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		,	CSS		= s.cssSaved || {}
          		;
          		// reset the zIndex
          		if (!s.isSliding && !s.isResizing)
          			$P.css("zIndex", c.zIndex.pane_normal);
          
          		// reset Overflow - if necessary
          		$P.css( CSS );
          
          		// clear var
          		s.cssSaved = false;
          	};
          
          
          	/**
          	* getBtn
          	*
          	* Helper function to validate params received by addButton utilities
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
          	*/
          	function getBtn(selector, pane, action) {
          		var
          			$E = $(selector)
          		,	err = "Error Adding Button \n\nInvalid "
          		;
          		if (!$E.length) // element not found
          			alert(err+"selector: "+ selector);
          		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
          			alert(err+"pane: "+ pane);
          		else { // VALID
          			var btn = options[pane].buttonClass +"-"+ action;
          			$E.addClass( btn +" "+ btn +"-"+ pane );
          			return $E;
          		}
          		return false;  // INVALID
          	};
          
          
          	/**
          	* addToggleBtn
          	*
          	* Add a custom Toggler button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addToggleBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "toggle");
          		if ($E)
          			$E
          				.attr("title", state[pane].isClosed ? "Open" : "Close")
          				.click(function (evt) {
          					toggle(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addOpenBtn
          	*
          	* Add a custom Open button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addOpenBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "open");
          		if ($E)
          			$E
          				.attr("title", "Open")
          				.click(function (evt) {
          					open(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addCloseBtn
          	*
          	* Add a custom Close button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addCloseBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "close");
          		if ($E)
          			$E
          				.attr("title", "Close")
          				.click(function (evt) {
          					close(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addPinBtn
          	*
          	* Add a custom Pin button for a pane
          	*
          	* Four classes are added to the element, based on the paneClass for the associated pane...
          	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
          	*  - ui-layout-pane-pin
          	*  - ui-layout-pane-west-pin
          	*  - ui-layout-pane-pin-up
          	*  - ui-layout-pane-west-pin-up
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
          	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
          	*/
          	function addPinBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "pin");
          		if ($E) {
          			var s = state[pane];
          			$E.click(function (evt) {
          				setPinState($(this), pane, (s.isSliding || s.isClosed));
          				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
          				else close( pane ); // slide-closed
          				evt.stopPropagation();
          			});
          			// add up/down pin attributes and classes
          			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
          			// add this pin to the pane data so we can 'sync it' automatically
          			// PANE.pins key is an array so we can store multiple pins for each pane
          			c[pane].pins.push( selector ); // just save the selector string
          		}
          	};
          
          	/**
          	* syncPinBtns
          	*
          	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
          	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
          	*
          	* @callers  open(), close()
          	* @params  pane   These are the params returned to callbacks by layout()
          	* @params  doPin  True means set the pin 'down', False means 'up'
          	*/
          	function syncPinBtns (pane, doPin) {
          		$.each(c[pane].pins, function (i, selector) {
          			setPinState($(selector), pane, doPin);
          		});
          	};
          
          	/**
          	* setPinState
          	*
          	* Change the class of the pin button to make it look 'up' or 'down'
          	*
          	* @callers  addPinBtn(), syncPinBtns()
          	* @param Element  $Pin		The pin-span element in a jQuery wrapper
          	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
          	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
          	*/
          	function setPinState ($Pin, pane, doPin) {
          		var updown = $Pin.attr("pin");
          		if (updown && doPin == (updown=="down")) return; // already in correct state
          		var
          			root	= options[pane].buttonClass
          		,	class1	= root +"-pin"
          		,	class2	= class1 +"-"+ pane
          		,	UP1		= class1 + "-up"
          		,	UP2		= class2 + "-up"
          		,	DN1		= class1 + "-down"
          		,	DN2		= class2 + "-down"
          		;
          		$Pin
          			.attr("pin", doPin ? "down" : "up") // logic
          			.attr("title", doPin ? "Un-Pin" : "Pin")
          			.removeClass( doPin ? UP1 : DN1 ) 
          			.removeClass( doPin ? UP2 : DN2 ) 
          			.addClass( doPin ? DN1 : UP1 ) 
          			.addClass( doPin ? DN2 : UP2 ) 
          		;
          	};
          
          
          /*
           * ###########################
           * CREATE/RETURN BORDER-LAYOUT
           * ###########################
           */
          
          	// init global vars
          	var 
          		$Container = $(this).css({ overflow: "hidden" }) // Container elem
          	,	$Ps		= {} // Panes x4	- set in initPanes()
          	,	$Cs		= {} // Content x4	- set in initPanes()
          	,	$Rs		= {} // Resizers x4	- set in initHandles()
          	,	$Ts		= {} // Togglers x4	- set in initHandles()
          	//	object aliases
          	,	c		= config // alias for config hash
          	,	cDims	= state.container // alias for easy access to 'container dimensions'
          	;
          
          	// create the border layout NOW
          	create();
          
          	// return object pointers to expose data & option Properties, and primary action Methods
          	return {
          		options:		options			// property - options hash
          	,	state:			state			// property - dimensions hash
          	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
          	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
          	,	open:			open			// method - ditto
          	,	close:			close			// method - ditto
          	,	hide:			hide			// method - ditto
          	,	show:			show			// method - ditto
          	,	resizeContent:	sizeContent		// method - ditto
          	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
          	,	resizeAll:		resizeAll		// method - no parameters
          	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
          	,	addOpenBtn:		addOpenBtn		// utility - ditto
          	,	addCloseBtn:	addCloseBtn		// utility - ditto
          	,	addPinBtn:		addPinBtn		// utility - ditto
          	,	allowOverflow:	allowOverflow	// utility - pass calling element
          	,	resetOverflow:	resetOverflow	// utility - ditto
          	,	cssWidth:		cssW
          	,	cssHeight:		cssH
          	};
          
          }
          })( jQuery );
          Evidence
          bug
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        32. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected 14 times, the first in the element starting with: " , togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (379 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 82920
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"82920-1230357900000"
          Last-Modified: Sat, 27 Dec 2008 06:05:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (82920 bytes)
          /*
           * jquery.layout 1.2.0
           *
           * Copyright (c) 2008 
           *   Fabrizio Balliano (http://www.fabrizioballiano.net)
           *   Kevin Dalman (http://allpro.net)
           *
           * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
           * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
           *
           * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
           * $Rev: 203 $
           * 
           * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
           */
          (function($) {
          
          $.fn.layout = function (opts) {
          
          /*
           * ###########################
           *   WIDGET CONFIG & OPTIONS
           * ###########################
           */
          
          	// DEFAULTS for options
          	var 
          		prefix = "ui-layout-" // prefix for ALL selectors and classNames
          	,	defaults = { //	misc default values
          			paneClass:				prefix+"pane"		// ui-layout-pane
          		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
          		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
          		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
          		,	buttonClass:			prefix+"button"		// ui-layout-button
          		,	contentSelector:		"."+prefix+"content"// ui-layout-content
          		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
          		}
          	;
          
          	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
          	var options = {
          		name:						""			// FUTURE REFERENCE - not used right now
          	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
          	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
          			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
          		,	closable:				true		// pane can open & close
          		,	resizable:				true		// when open, pane can be resized 
          		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
          		//,	paneSelector:			[ ]			// MUST be pane-specific!
          		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
          		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
          		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
          		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
          		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
          		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
          		,	resizerDragOpacity:		1			// option for ui.draggable
          		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
          		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
          		//,	size:					100			// inital size of pane - defaults are set 'per pane'
          		,	minSize:				0			// when manually resizing a pane
          		,	maxSize:				0			// ditto, 0 = no limit
          		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
          		,	spacing_closed:			6			// ditto - when pane is 'closed'
          		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
          		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
          		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
          		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
          		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
          		,	togglerTip_closed:		"Open"		// ditto
          		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
          		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
          		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
          		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
          		,	slideTrigger_close:		"mouseout"	// click, mouseout
          		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
          		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
          		,	togglerContent_closed:	""			// ditto
          		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
          		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
          		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
          		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
          		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
          		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
          		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
          		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
          		,	initClosed:				false		// true = init pane as 'closed'
          		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
          		
          		/*	callback options do not have to be set - listed here for reference only
          		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
          		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
          		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
          		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
          		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
          		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
          		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
          		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
          		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
          		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
          		*/
          		}
          	,	north: {
          			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
          		,	size:					"auto"
          		,	resizerCursor:			"n-resize"
          		}
          	,	south: {
          			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
          		,	size:					"auto"
          		,	resizerCursor:			"s-resize"
          		}
          	,	east: {
          			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
          		,	size:					200
          		,	resizerCursor:			"e-resize"
          		}
          	,	west: {
          			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
          		,	size:					200
          		,	resizerCursor:			"w-resize"
          		}
          	,	center: {
          			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
          		}
          
          	};
          
          
          	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
          		slide:	{
          			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	drop:	{
          			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	scale:	{
          			all:	{ duration:  "fast"	}
          		}
          	};
          
          
          	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
          	var config = {
          		allPanes:		"north,south,east,west,center"
          	,	borderPanes:	"north,south,east,west"
          	,	zIndex: { // set z-index values here
          			resizer_normal:	1		// normal z-index for resizer-bars
          		,	pane_normal:	2		// normal z-index for panes
          		,	mask:			4		// overlay div used to mask pane(s) during resizing
          		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
          		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
          		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
          		}
          	,	resizers: {
          			cssReq: {
          				position: 	"absolute"
          			,	padding: 	0
          			,	margin: 	0
          			,	fontSize:	"1px"
          			,	textAlign:	"left" // to counter-act "center" alignment!
          			,	overflow: 	"hidden" // keep toggler button from overflowing
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#DDD"
          			,	border:		"none"
          			}
          		}
          	,	togglers: {
          			cssReq: {
          				position: 	"absolute"
          			,	display: 	"block"
          			,	padding: 	0
          			,	margin: 	0
          			,	overflow:	"hidden"
          			,	textAlign:	"center"
          			,	fontSize:	"1px"
          			,	cursor: 	"pointer"
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#AAA"
          			}
          		}
          	,	content: {
          			cssReq: {
          				overflow:	"auto"
          			}
          		,	cssDef: {}
          		}
          	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
          			cssReq: {
          				position: 	"absolute"
          			,	margin:		0
          			,	zIndex: 	2
          			}
          		,	cssDef: {
          				padding:	"10px"
          			,	background:	"#FFF"
          			,	border:		"1px solid #BBB"
          			,	overflow:	"auto"
          			}
          		}
          	,	north: {
          			edge:			"top"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		0
          			,	bottom: 	"auto"
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	south: {
          			edge:			"bottom"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		"auto"
          			,	bottom: 	0
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	east: {
          			edge:			"right"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		"auto"
          			,	right: 		0
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	west: {
          			edge:			"left"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		0
          			,	right: 		"auto"
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	center: {
          			dir:			"center"
          		,	cssReq: {
          				left: 		"auto" // DYNAMIC
          			,	right: 		"auto" // DYNAMIC
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			,	width: 		"auto"
          			}
          		}
          	};
          
          
          	// DYNAMIC DATA
          	var state = {
          		// generate random 'ID#' to identify layout - used to create global namespace for timers
          		id:			Math.floor(Math.random() * 10000)
          	,	container:	{}
          	,	north:		{}
          	,	south:		{}
          	,	east:		{}
          	,	west:		{}
          	,	center:		{}
          	};
          
          
          	var 
          		altEdge = {
          			top:	"bottom"
          		,	bottom: "top"
          		,	left:	"right"
          		,	right:	"left"
          		}
          	,	altSide = {
          			north:	"south"
          		,	south:	"north"
          		,	east: 	"west"
          		,	west: 	"east"
          		}
          	;
          
          
          /*
           * ###########################
           *  INTERNAL HELPER FUNCTIONS
           * ###########################
           */
          
          	/**
          	 * isStr
          	 *
          	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
          	 */
          	var isStr = function (o) {
          		if (typeof o == "string")
          			return true;
          		else if (typeof o == "object") {
          			try {
          				var match = o.constructor.toString().match(/string/i); 
          				return (match !== null);
          			} catch (e) {} 
          		}
          		return false;
          	};
          
          	/**
          	 * str
          	 *
          	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
          	 *  else returns the original object
          	 */
          	var str = function (o) {
          		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
          		else return o;
          	};
          
          	/**
          	 * min / max
          	 *
          	 * Alias for Math.min/.max to simplify coding
          	 */
          	var min = function (x,y) { return Math.min(x,y); };
          	var max = function (x,y) { return Math.max(x,y); };
          
          	/**
          	 * transformData
          	 *
          	 * Processes the options passed in and transforms them into the format used by layout()
          	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
          	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
          	 * To update effects, options MUST use nested-keys format, with an effects key
          	 *
          	 * @callers  initOptions()
          	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
          	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
          	 */
          	var transformData = function (d) {
          		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
          		d = d || {};
          		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
          			json = $.extend( json, d ); // already in json format - add to base keys
          		else
          			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
          			$.each( d, function (key,val) {
          				a = key.split("__");
          				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
          			});
          		return json;
          	};
          
          	/**
          	 * setFlowCallback
          	 *
          	 * Set an INTERNAL callback to avoid simultaneous animation
          	 * Runs only if needed and only if all callbacks are not 'already set'!
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var setFlowCallback = function (action, pane, param) {
          		var
          			cb = action +","+ pane +","+ (param ? 1 : 0)
          		,	cP, cbPane
          		;
          		$.each(c.borderPanes.split(","), function (i,p) {
          			if (c[p].isMoving) {
          				bindCallback(p); // TRY to bind a callback
          				return false; // BREAK
          			}
          		});
          
          		function bindCallback (p, test) {
          			cP = c[p];
          			if (!cP.doCallback) {
          				cP.doCallback = true;
          				cP.callback = cb;
          			}
          			else { // try to 'chain' this callback
          				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
          				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
          					bindCallback (cpPane, true); // RECURSE
          			}
          		}
          	};
          
          	/**
          	 * execFlowCallback
          	 *
          	 * RUN the INTERNAL callback for this pane - if one exists
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var execFlowCallback = function (pane) {
          		var cP = c[pane];
          
          		// RESET flow-control flaGs
          		c.isLayoutBusy = false;
          		delete cP.isMoving;
          		if (!cP.doCallback || !cP.callback) return;
          
          		cP.doCallback = false; // RESET logic flag
          
          		// EXECUTE the callback
          		var
          			cb = cP.callback.split(",")
          		,	param = (cb[2] > 0 ? true : false)
          		;
          		if (cb[0] == "open")
          			open( cb[1], param  );
          		else if (cb[0] == "close")
          			close( cb[1], param );
          
          		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
          	};
          
          	/**
          	 * execUserCallback
          	 *
          	 * Executes a Callback function after a trigger event, like resize, open or close
          	 *
          	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
          	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
          	 */
          	var execUserCallback = function (pane, v_fn) {
          		if (!v_fn) return;
          		var fn;
          		try {
          			if (typeof v_fn == "function")
          				fn = v_fn;	
          			else if (typeof v_fn != "string")
          				return;
          			else if (v_fn.indexOf(",") > 0) {
          				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
          				var
          					args = v_fn.split(",")
          				,	fn = eval(args[0])
          				;
          				if (typeof fn=="function" && args.length > 1)
          					return fn(args[1]); // pass the argument parsed from 'list'
          			}
          			else // just the name of an external function?
          				fn = eval(v_fn);
          
          			if (typeof fn=="function")
          				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
          				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
          		}
          		catch (ex) {}
          	};
          
          	/**
          	 * cssNum
          	 *
          	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
          	 *
          	 * @callers  Called by many methods
          	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
          	 * @param String  property  The name of the CSS property, eg: top, width, etc.
          	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
          	 */
          	var cssNum = function ($E, prop) {
          		var
          			val = 0
          		,	hidden = false
          		,	visibility = ""
          		;
          		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
          			if ($.curCSS($E[0], "display", true) == "none") {
          				hidden = true;
          				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
          				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
          			}
          		}
          
          		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
          
          		if (hidden) { // WAS hidden, so put back the way it was
          			$E.css({ display: "none" });
          			if (visibility && visibility != "hidden")
          				$E.css({ visibility: visibility }); // reset 'visibility'
          		}
          
          		return val;
          	};
          
          	/**
          	 * cssW / cssH / cssSize
          	 *
          	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
          	 *
          	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
          	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
          	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
          	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
          	 *
          	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
          	 */
          	var cssW = function (e, outerWidth) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerWidth <= 0)
          			return 0;
          		else if (!(outerWidth>0))
          			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
          
          		if (!$.boxModel)
          			return outerWidth;
          
          		else // strip border and padding size from outerWidth to get CSS Width
          			return outerWidth
          				- cssNum($E, "paddingLeft")		
          				- cssNum($E, "paddingRight")
          				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
          				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
          			;
          	};
          	var cssH = function (e, outerHeight) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerHeight <= 0)
          			return 0;
          		else if (!(outerHeight>0))
          			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
          
          		if (!$.boxModel)
          			return outerHeight;
          
          		else // strip border and padding size from outerHeight to get CSS Height
          			return outerHeight
          				- cssNum($E, "paddingTop")
          				- cssNum($E, "paddingBottom")
          				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
          				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
          			;
          	};
          	var cssSize = function (pane, outerSize) {
          		if (c[pane].dir=="horz") // pane = north or south
          			return cssH(pane, outerSize);
          		else // pane = east or west
          			return cssW(pane, outerSize);
          	};
          
          	/**
          	 * getPaneSize
          	 *
          	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
          	 *
          	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
          	 */
          	var getPaneSize = function (pane, inclSpace) {
          		var 
          			$P	= $Ps[pane]
          		,	o	= options[pane]
          		,	s	= state[pane]
          		,	oSp	= (inclSpace ? o.spacing_open : 0)
          		,	cSp	= (inclSpace ? o.spacing_closed : 0)
          		;
          		if (!$P || s.isHidden)
          			return 0;
          		else if (s.isClosed || (s.isSliding && inclSpace))
          			return cSp;
          		else if (c[pane].dir == "horz")
          			return $P.outerHeight() + oSp;
          		else // dir == "vert"
          			return $P.outerWidth() + oSp;
          	};
          
          	var setPaneMinMaxSizes = function (pane) {
          		var 
          			d				= cDims
          		,	edge			= c[pane].edge
          		,	dir				= c[pane].dir
          		,	o				= options[pane]
          		,	s				= state[pane]
          		,	$P				= $Ps[pane]
          		,	$altPane		= $Ps[ altSide[pane] ]
          		,	paneSpacing		= o.spacing_open
          		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
          		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
          		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
          		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
          		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
          		,	minSize			= s.minSize || 0
          		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
          		,	minPos, maxPos	// used to set resizing limits
          		;
          		switch (pane) {
          			case "north":	minPos = d.offsetTop + minSize;
          							maxPos = d.offsetTop + maxSize;
          							break;
          			case "west":	minPos = d.offsetLeft + minSize;
          							maxPos = d.offsetLeft + maxSize;
          							break;
          			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
          							maxPos = d.offsetTop + d.innerHeight - minSize;
          							break;
          			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
          							maxPos = d.offsetLeft + d.innerWidth - minSize;
          							break;
          		}
          		// save data to pane-state
          		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
          	};
          
          	/**
          	 * getPaneDims
          	 *
          	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
          	 *
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
          	 */
          	var getPaneDims = function () {
          		var d = {
          			top:	getPaneSize("north", true) // true = include 'spacing' value for p
          		,	bottom:	getPaneSize("south", true)
          		,	left:	getPaneSize("west", true)
          		,	right:	getPaneSize("east", true)
          		,	width:	0
          		,	height:	0
          		};
          
          		with (d) {
          			width 	= cDims.innerWidth - left - right;
          			height 	= cDims.innerHeight - bottom - top;
          			// now add the 'container border/padding' to get final positions - relative to the container
          			top		+= cDims.top;
          			bottom	+= cDims.bottom;
          			left	+= cDims.left;
          			right	+= cDims.right;
          		}
          
          		return d;
          	};
          
          
          	/**
          	 * getElemDims
          	 *
          	 * Returns data for setting size of an element (container or a pane).
          	 *
          	 * @callers  create(), onWindowResize() for container, plus others for pane
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
          	 */
          	var getElemDims = function ($E) {
          		var
          			d = {} // dimensions hash
          		,	e, b, p // edge, border, padding
          		;
          
          		$.each("Left,Right,Top,Bottom".split(","), function () {
          			e = str(this);
          			b = d["border" +e] = cssNum($E, "border"+e+"Width");
          			p = d["padding"+e] = cssNum($E, "padding"+e);
          			d["offset" +e] = b + p; // total offset of content from outer edge
          			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
          			if ($E == $Container)
          				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
          		});
          
          		d.innerWidth  = d.outerWidth  = $E.outerWidth();
          		d.innerHeight = d.outerHeight = $E.outerHeight();
          		if ($.boxModel) {
          			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
          			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
          		}
          
          		return d;
          	};
          
          
          	var setTimer = function (pane, action, fn, ms) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) return; // timer already set!
          		else Timers[name] = setTimeout(fn, ms);
          	};
          
          	var clearTimer = function (pane, action) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) {
          			clearTimeout( Timers[name] );
          			delete Timers[name];
          			return true;
          		}
          		else
          			return false;
          	};
          
          
          /*
           * ###########################
           *   INITIALIZATION METHODS
           * ###########################
           */
          
          	/**
          	 * create
          	 *
          	 * Initialize the layout - called automatically whenever an instance of layout is created
          	 *
          	 * @callers  NEVER explicity called
          	 * @returns  An object pointer to the instance created
          	 */
          	var create = function () {
          		// initialize config/options
          		initOptions();
          
          		// initialize all objects
          		initContainer();	// set CSS as needed and init state.container dimensions
          		initPanes();		// size & position all panes
          		initHandles();		// create and position all resize bars & togglers buttons
          		initResizable();	// activate resizing on all panes where resizable=true
          		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
          
          		if (options.scrollToBookmarkOnLoad)
          			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
          
          		// bind hotkey function - keyDown - if required
          		initHotkeys();
          
          		// bind resizeAll() for 'this layout instance' to window.resize event
          		$(window).resize(function () {
          			var timerID = "timerLayout_"+state.id;
          			if (window[timerID]) clearTimeout(window[timerID]);
          			window[timerID] = null;
          			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
          				window[timerID] = setTimeout(resizeAll, 100);
          			else // most other browsers have a built-in delay before firing the resize event
          				resizeAll(); // resize all layout elements NOW!
          		});
          	};
          
          	/**
          	 * initContainer
          	 *
          	 * Validate and initialize container CSS and events
          	 *
          	 * @callers  create()
          	 */
          	var initContainer = function () {
          		try { // format html/body if this is a full page layout
          			if ($Container[0].tagName == "BODY") {
          				$("html").css({
          					height:		"100%"
          				,	overflow:	"hidden"
          				});
          				$("body").css({
          					position:	"relative"
          				,	height:		"100%"
          				,	overflow:	"hidden"
          				,	margin:		0
          				,	padding:	0		// TODO: test whether body-padding could be handled?
          				,	border:		"none"	// a body-border creates problems because it cannot be measured!
          				});
          			}
          			else { // set required CSS - overflow and position
          				var
          					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
          				,	p	= $Container.css("position")
          				,	h	= $Container.css("height")
          				;
          				// if this is a NESTED layout, then outer-pane ALREADY has position and height
          				if (!$Container.hasClass("ui-layout-pane")) {
          					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
          						CSS.position = "relative"; // container MUST have a 'position'
          					if (!h || h=="auto")
          						CSS.height = "100%"; // container MUST have a 'height'
          				}
          				$Container.css( CSS );
          			}
          		} catch (ex) {}
          
          		// get layout-container dimensions (updated when necessary)
          		cDims = state.container = getElemDims( $Container ); // update data-pointer too
          	};
          
          	/**
          	 * initHotkeys
          	 *
          	 * Bind layout hotkeys - if options enabled
          	 *
          	 * @callers  create()
          	 */
          	var initHotkeys = function () {
          		// bind keyDown to capture hotkeys, if option enabled for ANY pane
          		$.each(c.borderPanes.split(","), function (i,pane) {
          			var o = options[pane];
          			if (o.enableCursorHotkey || o.customHotkey) {
          				$(document).keydown( keyDown ); // only need to bind this ONCE
          				return false; // BREAK - binding was done
          			}
          		});
          	};
          
          	/**
          	 * initOptions
          	 *
          	 * Build final CONFIG and OPTIONS data
          	 *
          	 * @callers  create()
          	 */
          	var initOptions = function () {
          		// simplify logic by making sure passed 'opts' var has basic keys
          		opts = transformData( opts );
          
          		// update default effects, if case user passed key
          		if (opts.effects) {
          			$.extend( effects, opts.effects );
          			delete opts.effects;
          		}
          
          		// see if any 'global options' were specified
          		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
          			if (opts[key] !== undefined)
          				options[key] = opts[key];
          			else if (opts.defaults[key] !== undefined) {
          				options[key] = opts.defaults[key];
          				delete opts.defaults[key];
          			}
          		});
          
          		// remove any 'defaults' that MUST be set 'per-pane'
          		$.each("paneSelector,resizerCursor,customHotkey".split(","),
          			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
          		);
          
          		// now update options.defaults
          		$.extend( options.defaults, opts.defaults );
          		// make sure required sub-keys exist
          		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
          
          		// merge all config & options for the 'center' pane
          		c.center = $.extend( true, {}, c.defaults, c.center );
          		$.extend( options.center, opts.center );
          		// Most 'default options' do not apply to 'center', so add only those that DO
          		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
          		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
          			function (idx,key) { options.center[key] = o_Center[key]; }
          		);
          
          		var defs = options.defaults;
          
          		// create a COMPLETE set of options for EACH border-pane
          		$.each(c.borderPanes.split(","), function(i,pane) {
          			// apply 'pane-defaults' to CONFIG.PANE
          			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
          			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
          			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
          
          			// make sure we have base-classes
          			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
          			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
          			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
          
          			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
          			$.each(["_open","_close",""], function (i,n) { 
          				var
          					sName		= "fxName"+n
          				,	sSpeed		= "fxSpeed"+n
          				,	sSettings	= "fxSettings"+n
          				;
          				// recalculate fxName according to specificity rules
          				o[sName] =
          					opts[pane][sName]		// opts.west.fxName_open
          				||	opts[pane].fxName		// opts.west.fxName
          				||	opts.defaults[sName]	// opts.defaults.fxName_open
          				||	opts.defaults.fxName	// opts.defaults.fxName
          				||	o[sName]				// options.west.fxName_open
          				||	o.fxName				// options.west.fxName
          				||	defs[sName]				// options.defaults.fxName_open
          				||	defs.fxName				// options.defaults.fxName
          				||	"none"
          				;
          				// validate fxName to be sure is a valid effect
          				var fxName = o[sName];
          				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
          					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
          				// set vars for effects subkeys to simplify logic
          				var
          					fx = effects[fxName]	|| {} // effects.slide
          				,	fx_all	= fx.all		|| {} // effects.slide.all
          				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
          				;
          				// RECREATE the fxSettings[_open|_close] keys using specificity rules
          				o[sSettings] = $.extend(
          					{}
          				,	fx_all						// effects.slide.all
          				,	fx_pane						// effects.slide.west
          				,	defs.fxSettings || {}		// options.defaults.fxSettings
          				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
          				,	o.fxSettings				// options.west.fxSettings
          				,	o[sSettings]				// options.west.fxSettings_open
          				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
          				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
          				,	opts[pane].fxSettings		// opts.west.fxSettings
          				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
          				);
          				// recalculate fxSpeed according to specificity rules
          				o[sSpeed] =
          					opts[pane][sSpeed]		// opts.west.fxSpeed_open
          				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
          				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
          				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
          				||	o[sSpeed]				// options.west.fxSpeed_open
          				||	o[sSettings].duration	// options.west.fxSettings_open.duration
          				||	o.fxSpeed				// options.west.fxSpeed
          				||	o.fxSettings.duration	// options.west.fxSettings.duration
          				||	defs.fxSpeed			// options.defaults.fxSpeed
          				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
          				||	fx_pane.duration		// effects.slide.west.duration
          				||	fx_all.duration			// effects.slide.all.duration
          				||	"normal"				// DEFAULT
          				;
          				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
          			});
          		});
          	};
          
          	/**
          	 * initPanes
          	 *
          	 * Initialize module objects, styling, size and position for all panes
          	 *
          	 * @callers  create()
          	 */
          	var initPanes = function () {
          		// NOTE: do north & south FIRST so we can measure their height - do center LAST
          		$.each(c.allPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	fx		= s.fx
          			,	dir		= c[pane].dir
          			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
          			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
          			,	minSize	= o.minSize || 1
          			,	maxSize	= o.maxSize || 9999
          			,	spacing	= o.spacing_open || 0
          			,	sel		= o.paneSelector
          			,	isIE6	= ($.browser.msie && $.browser.version < 7)
          			,	CSS		= {}
          			,	$P, $C
          			;
          			$Cs[pane] = false; // init
          
          			if (sel.substr(0,1)==="#") // ID selector
          				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
          				$P = $Ps[pane] = $Container.find(sel+":first");
          			else { // class or other selector
          				$P = $Ps[pane] = $Container.children(sel+":first");
          				// look for the pane nested inside a 'form' element
          				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
          			}
          
          			if (!$P.length) {
          				$Ps[pane] = false; // logic
          				return true; // SKIP to next
          			}
          
          			// add basic classes & attributes
          			$P
          				.attr("pane", pane) // add pane-identifier
          				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
          			;
          
          			// init pane-logic vars, etc.
          			if (pane != "center") {
          				s.isClosed  = false; // true = pane is closed
          				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
          				s.isResizing= false; // true = pane is in process of being resized
          				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
          				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
          				// create special keys for internal use
          				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
          			}
          
          			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
          			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
          			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
          			CSS = {};	// reset var
          
          			// set css-position to account for container borders & padding
          			switch (pane) {
          				case "north": 	CSS.top 	= cDims.top;
          								CSS.left 	= cDims.left;
          								CSS.right	= cDims.right;
          								break;
          				case "south": 	CSS.bottom	= cDims.bottom;
          								CSS.left 	= cDims.left;
          								CSS.right 	= cDims.right;
          								break;
          				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
          								break;
          				case "east": 	CSS.right 	= cDims.right; // ditto
          								break;
          				case "center":	// top, left, width & height set by sizeMidPanes()
          			}
          
          			if (dir == "horz") { // north or south pane
          				if (size === 0 || size == "auto") {
          					$P.css({ height: "auto" });
          					size = $P.outerHeight();
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerHeight - spacing);
          				CSS.height = max(1, cssH(pane, size));
          				s.size = size; // update state
          				// make sure minSize is sufficient to avoid errors
          				s.maxSize = maxSize; // init value
          				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
          				// handle IE6
          				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
          				$P.css(CSS); // apply size & position
          			}
          			else if (dir == "vert") { // east or west pane
          				if (size === 0 || size == "auto") {
          					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
          					size = $P.outerWidth();
          					$P.css({ float: "none" }); // RESET
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerWidth - spacing);
          				CSS.width = max(1, cssW(pane, size));
          				s.size = size; // update state
          				s.maxSize = maxSize; // init value
          				// make sure minSize is sufficient to avoid errors
          				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
          				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
          				sizeMidPanes(pane, null, true); // true = onInit
          			}
          			else if (pane == "center") {
          				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
          				sizeMidPanes("center", null, true); // true = onInit
          			}
          
          			// close or hide the pane if specified in settings
          			if (o.initClosed && o.closable) {
          				$P.hide().addClass("closed");
          				s.isClosed = true;
          			}
          			else if (o.initHidden || o.initClosed) {
          				hide(pane, true); // will be completely invisible - no resizer or spacing
          				s.isHidden = true;
          			}
          			else
          				$P.addClass("open");
          
          			// check option for auto-handling of pop-ups & drop-downs
          			if (o.showOverflowOnHover)
          				$P.hover( allowOverflow, resetOverflow );
          
          			/*
          			 *	see if this pane has a 'content element' that we need to auto-size
          			 */
          			if (o.contentSelector) {
          				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
          				if (!$C.length) {
          					$Cs[pane] = false;
          					return true; // SKIP to next
          				}
          				$C.css( c.content.cssReq );
          				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
          				// NO PANE-SCROLLING when there is a content-div
          				$P.css({ overflow: "hidden" });
          			}
          		});
          	};
          
          	/**
          	 * initHandles
          	 *
          	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
          	 *
          	 * @callers  create()
          	 */
          	var initHandles = function () {
          		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	rClass	= o.resizerClass
          			,	tClass	= o.togglerClass
          			,	$P		= $Ps[pane]
          			;
          			$Rs[pane] = false; // INIT
          			$Ts[pane] = false;
          
          			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
          
          			var 
          				edge	= c[pane].edge
          			,	isOpen	= $P.is(":visible")
          			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
          			,	_pane	= "-"+ pane // used for classNames
          			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
          			,	$R, $T
          			;
          			// INIT RESIZER BAR
          			$R = $Rs[pane] = $("<span></span>");
          	
          			if (isOpen && o.resizable)
          				; // this is handled by initResizable
          			else if (!isOpen && o.slidable)
          				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
          	
          			$R
          				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
          				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
          				.attr("resizer", pane) // so we can read this from the resizer
          				.css(c.resizers.cssReq) // add base/required styles
          				// POSITION of resizer bar - allow for container border & padding
          				.css(edge, cDims[edge] + getPaneSize(pane))
          				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
          				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
          				.appendTo($Container) // append DIV to container
          			;
          			 // ADD VISUAL STYLES
          			if (o.applyDefaultStyles)
          				$R.css(c.resizers.cssDef);
          
          			if (o.closable) {
          				// INIT COLLAPSER BUTTON
          				$T = $Ts[pane] = $("<div></div>");
          				$T
          					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
          					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
          					.css(c.togglers.cssReq) // add base/required styles
          					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
          					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
          					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
          					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
          					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
          					.appendTo($R) // append SPAN to resizer DIV
          				;
          
          				// ADD INNER-SPANS TO TOGGLER
          				if (o.togglerContent_open) // ui-layout-open
          					$("<span>"+ o.togglerContent_open +"</span>")
          						.addClass("content content-open")
          						.css("display", s.isClosed ? "none" : "block")
          						.appendTo( $T )
          					;
          				if (o.togglerContent_closed) // ui-layout-closed
          					$("<span>"+ o.togglerContent_closed +"</span>")
          						.addClass("content content-closed")
          						.css("display", s.isClosed ? "block" : "none")
          						.appendTo( $T )
          					;
          
          				 // ADD BASIC VISUAL STYLES
          				if (o.applyDefaultStyles)
          					$T.css(c.togglers.cssDef);
          
          				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          			}
          
          		});
          
          		// SET ALL HANDLE SIZES & LENGTHS
          		sizeHandles("all", true); // true = onInit
          	};
          
          	/**
          	 * initResizable
          	 *
          	 * Add resize-bars to all panes that specify it in options
          	 *
          	 * @dependancies  $.fn.resizable - will abort if not found
          	 * @callers  create()
          	 */
          	var initResizable = function () {
          		var
          			draggingAvailable = (typeof $.fn.draggable == "function")
          		,	minPosition, maxPosition, edge // set in start()
          		;
          
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			;
          			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
          				o.resizable = false;
          				return true; // skip to next
          			}
          
          			var 
          				rClass				= o.resizerClass
          			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
          			,	dragClass			= rClass+"-drag"			// resizer-drag
          			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
          			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
          			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
          			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
          			,	draggingClassSet	= false 					// logic var
          			,	$P 					= $Ps[pane]
          			,	$R					= $Rs[pane]
          			;
          
          			if (!s.isClosed)
          				$R
          					.attr("title", o.resizerTip)
          					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
          				;
          
          			$R.draggable({
          				containment:	$Container[0] // limit resizing to layout container
          			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
          			,	delay:			200
          			,	distance:		1
          			//	basic format for helper - style it using class: .ui-draggable-dragging
          			,	helper:			"clone"
          			,	opacity:		o.resizerDragOpacity
          			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
          			,	zIndex:			c.zIndex.resizing
          
          			,	start: function (e, ui) {
          					// onresize_start callback - will CANCEL hide if returns false
          					// TODO: CONFIRM that dragging can be cancelled like this???
          					if (false === execUserCallback(pane, o.onresize_start)) return false;
          
          					s.isResizing = true; // prevent pane from closing while resizing
          					clearTimer(pane, "closeSlider"); // just in case already triggered
          
          					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
          					draggingClassSet = false; // reset logic var - see drag()
          
          					// SET RESIZING LIMITS - used in drag()
          					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
          					setPaneMinMaxSizes(pane); // update pane-state
          					s.minPosition -= resizerWidth;
          					s.maxPosition -= resizerWidth;
          					edge = (c[pane].dir=="horz" ? "top" : "left");
          
          					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
          					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
          						$('<div class="ui-layout-mask"/>')
          							.css({
          								background:	"#fff"
          							,	opacity:	"0.001"
          							,	zIndex:		9
          							,	position:	"absolute"
          							,	width:		this.offsetWidth+"px"
          							,	height:		this.offsetHeight+"px"
          							})
          							.css($(this).offset()) // top & left
          							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
          						;
          					});
          				}
          
          			,	drag: function (e, ui) {
          					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
          						$(".ui-draggable-dragging")
          							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
          							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
          						;
          						draggingClassSet = true;
          						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
          						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
          					}
          					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
          					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
          					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
          				}
          
          			,	stop: function (e, ui) {
          					var 
          						dragPos	= ui.position
          					,	resizerPos
          					,	newSize
          					;
          					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
          	
          					switch (pane) {
          						case "north":	resizerPos = dragPos.top; break;
          						case "west":	resizerPos = dragPos.left; break;
          						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
          						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
          					}
          					// remove container margin from resizer position to get the pane size
          					newSize = resizerPos - cDims[ c[pane].edge ];
          
          					sizePane(pane, newSize);
          
          					// UN-MASK PANES MASKED IN drag.start
          					$("div.ui-layout-mask").remove(); // Remove iframe masks	
          
          					s.isResizing = false;
          				}
          
          			});
          		});
          	};
          
          
          
          /*
           * ###########################
           *       ACTION METHODS
           * ###########################
           */
          
          	/**
          	 * hide / show
          	 *
          	 * Completely 'hides' a pane, including its spacing - as if it does not exist
          	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
          	 *
          	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
          	 */
          	var hide = function (pane, onInit) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onhide_start)) return;
          
          		s.isSliding = false; // just in case
          
          		// now hide the elements
          		if ($R) $R.hide(); // hide resizer-bar
          		if (onInit || s.isClosed) {
          			s.isClosed = true; // to trigger open-animation on show()
          			s.isHidden  = true;
          			$P.hide(); // no animation when loading page
          			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          			execUserCallback(pane, o.onhide_end || o.onhide);
          		}
          		else {
          			s.isHiding = true; // used by onclose
          			close(pane, false); // adjust all panes to fit
          			//s.isHidden  = true; - will be set by close - if not cancelled
          		}
          	};
          
          	var show = function (pane, openPane) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onshow_start)) return;
          
          		s.isSliding = false; // just in case
          		s.isShowing = true; // used by onopen/onclose
          		//s.isHidden  = false; - will be set by open/close - if not cancelled
          
          		// now show the elements
          		if ($R && o.spacing_open > 0) $R.show();
          		if (openPane === false)
          			close(pane, true); // true = force
          		else
          			open(pane); // adjust all panes to fit
          	};
          
          
          	/**
          	 * toggle
          	 *
          	 * Toggles a pane open/closed by calling either open or close
          	 *
          	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
          	 */
          	var toggle = function (pane) {
          		var s = state[pane];
          		if (s.isHidden)
          			show(pane); // will call 'open' after unhiding it
          		else if (s.isClosed)
          			open(pane);
          		else
          			close(pane);
          	};
          
          	/**
          	 * close
          	 *
          	 * Close the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being closed, ie: north, south, east, or west
          	 */
          	var close = function (pane, force, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_sliding= "-sliding"
          		,	_closed	= "-closed"
          		// 	transfer logic vars to temp vars
          		,	isShowing = s.isShowing
          		,	isHiding = s.isHiding
          		;
          		// now clear the logic vars
          		delete s.isShowing;
          		delete s.isHiding;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!force && s.isClosed && !isShowing) return; // already closed
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("close", pane, force); // set a callback for this action, if possible
          			return; // ABORT 
          		}
          
          		// onclose_start callback - will CANCEL hide if returns false
          		// SKIP if just 'showing' a hidden pane as 'closed'
          		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		s.isClosed = true;
          		// update isHidden BEFORE sizing panes
          		if (isHiding) s.isHidden = true;
          		else if (isShowing) s.isHidden = false;
          
          		// sync any 'pin buttons'
          		syncPinBtns(pane, false);
          
          		// resize panes adjacent to this one
          		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          
          		// if this pane has a resizer bar, move it now
          		if ($R) {
          			$R
          				.css(edge, cDims[edge]) // move the resizer bar
          				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
          				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
          				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
          			;
          			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
          			if (o.resizable)
          				$R
          					.draggable("disable")
          					.css("cursor", "default")
          					.attr("title","")
          				;
          			// if pane has a toggler button, adjust that too
          			if ($T) {
          				$T
          					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
          					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
          					.attr("title", o.togglerTip_closed) // may be blank
          				;
          			}
          			sizeHandles(); // resize 'length' and position togglers for adjacent panes
          		}
          
          		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
          		if (doFX) {
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
          				lockPaneForFX(pane, false); // undo
          				if (!s.isClosed) return; // pane was opened before animation finished!
          				close_2();
          			});
          		}
          		else {
          			$P.hide(); // just hide pane NOW
          			close_2();
          		}
          
          		// SUBROUTINE
          		function close_2 () {
          			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          
          			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
          			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
          			// onhide OR onshow callback
          			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
          			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          
          	/**
          	 * open
          	 *
          	 * Open the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being opened, ie: north, south, east, or west
          	 */
          	var open = function (pane, slide, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_closed	= "-closed"
          		,	_sliding= "-sliding"
          		// 	transfer logic var to temp var
          		,	isShowing = s.isShowing
          		;
          		// now clear the logic var
          		delete s.isShowing;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!s.isClosed && !s.isSliding) return; // already open
          
          		// pane can ALSO be unhidden by just calling show(), so handle this scenario
          		if (s.isHidden && !isShowing) {
          			show(pane, true);
          			return;
          		}
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
          			return; // ABORT
          		}
          
          		// onopen_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onopen_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		// 'PIN PANE' - stop sliding
          		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
          			bindStopSlidingEvents(pane, false); // will set isSliding=false
          
          		s.isClosed = false;
          		// update isHidden BEFORE sizing panes
          		if (isShowing) s.isHidden = false;
          
          		// Container size may have changed - shrink the pane if now 'too big'
          		setPaneMinMaxSizes(pane); // update pane-state
          		if (s.size > s.maxSize) // pane is too big! resize it before opening
          			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
          
          		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
          
          		if (doFX) { // ANIMATE
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
          				lockPaneForFX(pane, false); // undo
          				if (s.isClosed) return; // pane was closed before animation finished!
          				open_2(); // continue
          			});
          		}
          		else {// no animation
          			$P.show();	// just show pane and...
          			open_2();	// continue
          		}
          
          		// SUBROUTINE
          		function open_2 () {
          			// NOTE: if isSliding, then other panes are NOT 'resized'
          			if (!s.isSliding) // resize all panes adjacent to this one
          				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
          
          			// if this pane has a toggler, move it now
          			if ($R) {
          				$R
          					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
          					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
          					.addClass( rClass+_open +" "+ rClass+_pane+_open )
          					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
          				;
          				if (o.resizable)
          					$R
          						.draggable("enable")
          						.css("cursor", o.resizerCursor)
          						.attr("title", o.resizerTip)
          					;
          				else
          					$R.css("cursor", "default"); // n-resize, s-resize, etc
          				// if pane also has a toggler button, adjust that too
          				if ($T) {
          					$T
          						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
          						.addClass( tClass+_open +" "+ tClass+_pane+_open )
          						.attr("title", o.togglerTip_open) // may be blank
          					;
          				}
          				sizeHandles("all"); // resize resizer & toggler sizes for all panes
          			}
          
          			// resize content every time pane opens - to be sure
          			sizeContent(pane);
          
          			// sync any 'pin buttons'
          			syncPinBtns(pane, !s.isSliding);
          
          			// onopen callback
          			execUserCallback(pane, o.onopen_end || o.onopen);
          
          			// onshow callback
          			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          	
          
          	/**
          	 * lockPaneForFX
          	 *
          	 * Must set left/top on East/South panes so animation will work properly
          	 *
          	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
          	 * @param Boolean  doLock  true = set left/top, false = remove
          	 */
          	var lockPaneForFX = function (pane, doLock) {
          		var $P = $Ps[pane];
          		if (doLock) {
          			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
          			if (pane=="south")
          				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
          			else if (pane=="east")
          				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
          		}
          		else {
          			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
          			if (pane=="south")
          				$P.css({ top: "auto" });
          			else if (pane=="east")
          				$P.css({ left: "auto" });
          		}
          	};
          
          
          	/**
          	 * bindStartSlidingEvent
          	 *
          	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
          	 *
          	 * @callers  open(), close()
          	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
          	 * @param Boolean  enable  Enable or Disable sliding?
          	 */
          	var bindStartSlidingEvent = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	$R		= $Rs[pane]
          		,	trigger	= o.slideTrigger_open
          		;
          		if (!$R || !o.slidable) return;
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
          		$R
          			// add or remove trigger event
          			[enable ? "bind" : "unbind"](trigger, slideOpen)
          			// set the appropriate cursor & title/tip
          			.css("cursor", (enable ? o.sliderCursor: "default"))
          			.attr("title", (enable ? o.sliderTip : ""))
          		;
          	};
          
          	/**
          	 * bindStopSlidingEvents
          	 *
          	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
          	 * Also increases zIndex when pane is sliding open
          	 * See bindStartSlidingEvent for code to control 'slide open'
          	 *
          	 * @callers  slideOpen(), slideClosed()
          	 * @param String  pane  The pane to process, 'north', 'south', etc.
          	 * @param Boolean  isOpen  Is pane open or closed?
          	 */
          	var bindStopSlidingEvents = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	s		= state[pane]
          		,	trigger	= o.slideTrigger_close
          		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          
          		s.isSliding = enable; // logic
          		clearTimer(pane, "closeSlider"); // just in case
          
          		// raise z-index when sliding
          		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
          		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
          
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
          
          		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
          		if (enable) { // BIND trigger events
          			$P.bind(trigger, slideClosed );
          			$R.bind(trigger, slideClosed );
          			if (trigger = "mouseout") {
          				$P.bind("mouseover", cancelMouseOut );
          				$R.bind("mouseover", cancelMouseOut );
          			}
          		}
          		else { // UNBIND trigger events
          			// TODO: why does unbind of a 'single function' not work reliably?
          			//$P[action](trigger, slideClosed );
          			$P.unbind(trigger);
          			$R.unbind(trigger);
          			if (trigger = "mouseout") {
          				//$P[action]("mouseover", cancelMouseOut );
          				$P.unbind("mouseover");
          				$R.unbind("mouseover");
          				clearTimer(pane, "closeSlider");
          			}
          		}
          
          		// SUBROUTINE for mouseout timer clearing
          		function cancelMouseOut (evt) {
          			clearTimer(pane, "closeSlider");
          			evt.stopPropagation();
          		}
          	};
          
          	var slideOpen = function () {
          		var pane = $(this).attr("resizer"); // attr added by initHandles
          		if (state[pane].isClosed) { // skip if already open!
          			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
          			open(pane, true); // true = slide - ie, called from here!
          		}
          	};
          
          	var slideClosed = function () {
          		var
          			$E = $(this)
          		,	pane = $E.attr("pane") || $E.attr("resizer")
          		,	o = options[pane]
          		,	s = state[pane]
          		;
          		if (s.isClosed || s.isResizing)
          			return; // skip if already closed OR in process of resizing
          		else if (o.slideTrigger_close == "click")
          			close_NOW(); // close immediately onClick
          		else // trigger = mouseout - use a delay
          			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
          
          		// SUBROUTINE for timed close
          		function close_NOW () {
          			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
          			if (!s.isClosed) close(pane); // skip if already closed!
          		}
          	};
          
          
          	/**
          	 * sizePane
          	 *
          	 * @callers  initResizable.stop()
          	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
          	 * @param Integer  newSize  The new size for this pane - will be validated
          	 */
          	var sizePane = function (pane, size) {
          		// TODO: accept "auto" as size, and size-to-fit pane content
          		var 
          			edge	= c[pane].edge
          		,	dir		= c[pane].dir
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          		// calculate 'current' min/max sizes
          		setPaneMinMaxSizes(pane); // update pane-state
          		// compare/update calculated min/max to user-options
          		s.minSize = max(s.minSize, o.minSize);
          		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
          		// validate passed size
          		size = max(size, s.minSize);
          		size = min(size, s.maxSize);
          		s.size = size; // update state
          
          		// move the resizer bar and resize the pane
          		$R.css( edge, size + cDims[edge] );
          		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
          
          		// resize all the adjacent panes, and adjust their toggler buttons
          		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
          		sizeHandles();
          		sizeContent(pane);
          		execUserCallback(pane, o.onresize_end || o.onresize);
          	};
          
          	/**
          	 * sizeMidPanes
          	 *
          	 * @callers  create(), open(), close(), onWindowResize()
          	 */
          	var sizeMidPanes = function (panes, overrideDims, onInit) {
          		if (!panes || panes == "all") panes = "east,west,center";
          
          		var d = getPaneDims();
          		if (overrideDims) $.extend( d, overrideDims );
          
          		$.each(panes.split(","), function() {
          			if (!$Ps[this]) return; // NO PANE - skip
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	hasRoom	= true
          			,	CSS		= {}
          			;
          
          			if (pane == "center") {
          				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
          				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
          				CSS.width  = max(1, cssW(pane, CSS.width));
          				CSS.height = max(1, cssH(pane, CSS.height));
          				hasRoom = (CSS.width > 1 && CSS.height > 1);
          				/*
          				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
          				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
          				 */
          				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
          					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
          					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
          				}
          			}
          			else { // for east and west, set only the height
          				CSS.top = d.top;
          				CSS.bottom = d.bottom;
          				CSS.height = max(1, cssH(pane, d.height));
          				hasRoom = (CSS.height > 1);
          			}
          
          			if (hasRoom) {
          				$P.css(CSS);
          				if (s.noRoom) {
          					s.noRoom = false;
          					if (s.isHidden) return;
          					else show(pane, !s.isClosed);
          					/* OLD CODE - keep until sure line above works right!
          					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
          					if ($R) $R.show();
          					*/
          				}
          				if (!onInit) {
          					sizeContent(pane);
          					execUserCallback(pane, o.onresize_end || o.onresize);
          				}
          			}
          			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
          				s.noRoom = true; // update state
          				if (s.isHidden) return;
          				if (onInit) { // skip onhide callback and other logic onLoad
          					$P.hide();
          					if ($R) $R.hide();
          				}
          				else hide(pane);
          			}
          		});
          	};
          
          
          	var sizeContent = function (panes) {
          		if (!panes || panes == "all") panes = c.allPanes;
          
          		$.each(panes.split(","), function() {
          			if (!$Cs[this]) return; // NO CONTENT - skip
          			var 
          				pane	= str(this)
          			,	ignore	= options[pane].contentIgnoreSelector
          			,	$P		= $Ps[pane]
          			,	$C		= $Cs[pane]
          			,	e_C		= $C[0]		// DOM element
          			,	height	= cssH($P);	// init to pane.innerHeight
          			;
          			$P.children().each(function() {
          				if (this == e_C) return; // Content elem - skip
          				var $E = $(this);
          				if (!ignore || !$E.is(ignore))
          					height -= $E.outerHeight();
          			});
          			if (height > 0)
          				height = cssH($C, height);
          			if (height < 1)
          				$C.hide(); // no room for content!
          			else
          				$C.css({ height: height }).show();
          		});
          	};
          
          
          	/**
          	 * sizeHandles
          	 *
          	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
          	 *
          	 * @callers  initHandles(), open(), close(), resizeAll()
          	 */
          	var sizeHandles = function (panes, onInit) {
          		if (!panes || panes == "all") panes = c.borderPanes;
          
          		$.each(panes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	$T		= $Ts[pane]
          			;
          			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
          
          			var 
          				dir			= c[pane].dir
          			,	_state		= (s.isClosed ? "_closed" : "_open")
          			,	spacing		= o["spacing"+ _state]
          			,	togAlign	= o["togglerAlign"+ _state]
          			,	togLen		= o["togglerLength"+ _state]
          			,	paneLen
          			,	offset
          			,	CSS = {}
          			;
          			if (spacing == 0) {
          				$R.hide();
          				return;
          			}
          			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
          				$R.show(); // in case was previously hidden
          
          			// Resizer Bar is ALWAYS same width/height of pane it is attached to
          			if (dir == "horz") { // north/south
          				paneLen = $P.outerWidth();
          				$R.css({
          					width:	max(1, cssW($R, paneLen)) // account for borders & padding
          				,	height:	max(1, cssH($R, spacing)) // ditto
          				,	left:	cssNum($P, "left")
          				});
          			}
          			else { // east/west
          				paneLen = $P.outerHeight();
          				$R.css({
          					height:	max(1, cssH($R, paneLen)) // account for borders & padding
          				,	width:	max(1, cssW($R, spacing)) // ditto
          				,	top:	cDims.top + getPaneSize("north", true)
          				//,	top:	cssNum($Ps["center"], "top")
          				});
          				
          			}
          
          			if ($T) {
          				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
          					$T.hide(); // always HIDE the toggler when 'sliding'
          					return;
          				}
          				else
          					$T.show(); // in case was previously hidden
          
          				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
          					togLen = paneLen;
          					offset = 0;
          				}
          				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
          					if (typeof togAlign == "string") {
          						switch (togAlign) {
          							case "top":
          							case "left":	offset = 0;
          											break;
          							case "bottom":
          							case "right":	offset = paneLen - togLen;
          											break;
          							case "middle":
          							case "center":
          							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
          						}
          					}
          					else { // togAlign = number
          						var x = parseInt(togAlign); //
          						if (togAlign >= 0) offset = x;
          						else offset = paneLen - togLen + x; // NOTE: x is negative!
          					}
          				}
          
          				var
          					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
          				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
          				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
          				;
          				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
          				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
          
          				if (dir == "horz") { // north/south
          					var width = cssW($T, togLen);
          					$T.css({
          						width:	max(0, width)  // account for borders & padding
          					,	height:	max(1, cssH($T, spacing)) // ditto
          					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
          				}
          				else { // east/west
          					var height = cssH($T, togLen);
          					$T.css({
          						height:	max(0, height)  // account for borders & padding
          					,	width:	max(1, cssW($T, spacing)) // ditto
          					,	top:	offset // POSITION the toggler
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
          				}
          
          
          			}
          
          			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
          			if (onInit && o.initHidden) {
          				$R.hide();
          				if ($T) $T.hide();
          			}
          		});
          	};
          
          
          	/**
          	 * resizeAll
          	 *
          	 * @callers  window.onresize(), callbacks or custom code
          	 */
          	var resizeAll = function () {
          		var
          			oldW	= cDims.innerWidth
          		,	oldH	= cDims.innerHeight
          		;
          		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
          
          		var
          			checkH	= (cDims.innerHeight < oldH)
          		,	checkW	= (cDims.innerWidth < oldW)
          		,	s, dir
          		;
          
          		if (checkH || checkW)
          			// NOTE special order for sizing: S-N-E-W
          			$.each(["south","north","east","west"], function(i,pane) {
          				s = state[pane];
          				dir = c[pane].dir;
          				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
          					setPaneMinMaxSizes(pane); // update pane-state
          					// shrink pane if 'too big' to fit
          					if (s.size > s.maxSize)
          						sizePane(pane, s.maxSize);
          				}
          			});
          
          		sizeMidPanes("all");
          		sizeHandles("all"); // reposition the toggler elements
          	};
          
          
          	/**
          	 * keyDown
          	 *
          	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
          	 *
          	 * @callers  document.keydown()
          	 */
          	function keyDown (evt) {
          		if (!evt) return true;
          		var code = evt.keyCode;
          		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
          
          		var
          			PANE = {
          				38: "north" // Up Cursor
          			,	40: "south" // Down Cursor
          			,	37: "west"  // Left Cursor
          			,	39: "east"  // Right Cursor
          			}
          		,	isCursorKey = (code >= 37 && code <= 40)
          		,	ALT = evt.altKey // no worky!
          		,	SHIFT = evt.shiftKey
          		,	CTRL = evt.ctrlKey
          		,	pane = false
          		,	s, o, k, m, el
          		;
          
          		if (!CTRL && !SHIFT)
          			return true; // no modifier key - abort
          		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
          			pane = PANE[code];
          		else // check to see if this matches a custom-hotkey
          			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
          				o = options[p];
          				k = o.customHotkey;
          				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
          				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
          					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
          						pane = p;
          						return false; // BREAK
          					}
          				}
          			});
          
          		if (!pane) return true; // no hotkey - abort
          
          		// validate pane
          		o = options[pane]; // get pane options
          		s = state[pane]; // get pane options
          		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
          
          		// see if user is in a 'form field' because may be 'selecting text'!
          		el = evt.target || evt.srcElement;
          		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
          			return true; // allow text-selection
          
          		// SYNTAX NOTES
          		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
          		// use "return false" to abort keystroke AND abort function
          		toggle(pane);
          		evt.stopPropagation();
          		evt.returnValue = false; // CANCEL key
          		return false;
          	};
          
          
          /*
           * ###########################
           *     UTILITY METHODS
           *   called externally only
           * ###########################
           */
          
          	function allowOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).attr("pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		;
          
          		// if pane is already raised, then reset it before doing it again!
          		// this would happen if allowOverflow is attached to BOTH the pane and an element 
          		if (s.cssSaved)
          			resetOverflow(pane); // reset previous CSS before continuing
          
          		// if pane is raised by sliding or resizing, or it's closed, then abort
          		if (s.isSliding || s.isResizing || s.isClosed) {
          			s.cssSaved = false;
          			return;
          		}
          
          		var
          			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
          		,	curCSS	= {}
          		,	of		= $P.css("overflow")
          		,	ofX		= $P.css("overflowX")
          		,	ofY		= $P.css("overflowY")
          		;
          		// determine which, if any, overflow settings need to be changed
          		if (of != "visible") {
          			curCSS.overflow = of;
          			newCSS.overflow = "visible";
          		}
          		if (ofX && ofX != "visible" && ofX != "auto") {
          			curCSS.overflowX = ofX;
          			newCSS.overflowX = "visible";
          		}
          		if (ofY && ofY != "visible" && ofY != "auto") {
          			curCSS.overflowY = ofX;
          			newCSS.overflowY = "visible";
          		}
          
          		// save the current overflow settings - even if blank!
          		s.cssSaved = curCSS;
          
          		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
          		$P.css( newCSS );
          
          		// make sure the zIndex of all other panes is normal
          		$.each(c.allPanes.split(","), function(i, p) {
          			if (p != pane) resetOverflow(p);
          		});
          
          	};
          
          	function resetOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		,	CSS		= s.cssSaved || {}
          		;
          		// reset the zIndex
          		if (!s.isSliding && !s.isResizing)
          			$P.css("zIndex", c.zIndex.pane_normal);
          
          		// reset Overflow - if necessary
          		$P.css( CSS );
          
          		// clear var
          		s.cssSaved = false;
          	};
          
          
          	/**
          	* getBtn
          	*
          	* Helper function to validate params received by addButton utilities
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
          	*/
          	function getBtn(selector, pane, action) {
          		var
          			$E = $(selector)
          		,	err = "Error Adding Button \n\nInvalid "
          		;
          		if (!$E.length) // element not found
          			alert(err+"selector: "+ selector);
          		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
          			alert(err+"pane: "+ pane);
          		else { // VALID
          			var btn = options[pane].buttonClass +"-"+ action;
          			$E.addClass( btn +" "+ btn +"-"+ pane );
          			return $E;
          		}
          		return false;  // INVALID
          	};
          
          
          	/**
          	* addToggleBtn
          	*
          	* Add a custom Toggler button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addToggleBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "toggle");
          		if ($E)
          			$E
          				.attr("title", state[pane].isClosed ? "Open" : "Close")
          				.click(function (evt) {
          					toggle(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addOpenBtn
          	*
          	* Add a custom Open button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addOpenBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "open");
          		if ($E)
          			$E
          				.attr("title", "Open")
          				.click(function (evt) {
          					open(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addCloseBtn
          	*
          	* Add a custom Close button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addCloseBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "close");
          		if ($E)
          			$E
          				.attr("title", "Close")
          				.click(function (evt) {
          					close(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addPinBtn
          	*
          	* Add a custom Pin button for a pane
          	*
          	* Four classes are added to the element, based on the paneClass for the associated pane...
          	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
          	*  - ui-layout-pane-pin
          	*  - ui-layout-pane-west-pin
          	*  - ui-layout-pane-pin-up
          	*  - ui-layout-pane-west-pin-up
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
          	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
          	*/
          	function addPinBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "pin");
          		if ($E) {
          			var s = state[pane];
          			$E.click(function (evt) {
          				setPinState($(this), pane, (s.isSliding || s.isClosed));
          				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
          				else close( pane ); // slide-closed
          				evt.stopPropagation();
          			});
          			// add up/down pin attributes and classes
          			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
          			// add this pin to the pane data so we can 'sync it' automatically
          			// PANE.pins key is an array so we can store multiple pins for each pane
          			c[pane].pins.push( selector ); // just save the selector string
          		}
          	};
          
          	/**
          	* syncPinBtns
          	*
          	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
          	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
          	*
          	* @callers  open(), close()
          	* @params  pane   These are the params returned to callbacks by layout()
          	* @params  doPin  True means set the pin 'down', False means 'up'
          	*/
          	function syncPinBtns (pane, doPin) {
          		$.each(c[pane].pins, function (i, selector) {
          			setPinState($(selector), pane, doPin);
          		});
          	};
          
          	/**
          	* setPinState
          	*
          	* Change the class of the pin button to make it look 'up' or 'down'
          	*
          	* @callers  addPinBtn(), syncPinBtns()
          	* @param Element  $Pin		The pin-span element in a jQuery wrapper
          	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
          	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
          	*/
          	function setPinState ($Pin, pane, doPin) {
          		var updown = $Pin.attr("pin");
          		if (updown && doPin == (updown=="down")) return; // already in correct state
          		var
          			root	= options[pane].buttonClass
          		,	class1	= root +"-pin"
          		,	class2	= class1 +"-"+ pane
          		,	UP1		= class1 + "-up"
          		,	UP2		= class2 + "-up"
          		,	DN1		= class1 + "-down"
          		,	DN2		= class2 + "-down"
          		;
          		$Pin
          			.attr("pin", doPin ? "down" : "up") // logic
          			.attr("title", doPin ? "Un-Pin" : "Pin")
          			.removeClass( doPin ? UP1 : DN1 ) 
          			.removeClass( doPin ? UP2 : DN2 ) 
          			.addClass( doPin ? DN1 : UP1 ) 
          			.addClass( doPin ? DN2 : UP2 ) 
          		;
          	};
          
          
          /*
           * ###########################
           * CREATE/RETURN BORDER-LAYOUT
           * ###########################
           */
          
          	// init global vars
          	var 
          		$Container = $(this).css({ overflow: "hidden" }) // Container elem
          	,	$Ps		= {} // Panes x4	- set in initPanes()
          	,	$Cs		= {} // Content x4	- set in initPanes()
          	,	$Rs		= {} // Resizers x4	- set in initHandles()
          	,	$Ts		= {} // Togglers x4	- set in initHandles()
          	//	object aliases
          	,	c		= config // alias for config hash
          	,	cDims	= state.container // alias for easy access to 'container dimensions'
          	;
          
          	// create the border layout NOW
          	create();
          
          	// return object pointers to expose data & option Properties, and primary action Methods
          	return {
          		options:		options			// property - options hash
          	,	state:			state			// property - dimensions hash
          	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
          	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
          	,	open:			open			// method - ditto
          	,	close:			close			// method - ditto
          	,	hide:			hide			// method - ditto
          	,	show:			show			// method - ditto
          	,	resizeContent:	sizeContent		// method - ditto
          	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
          	,	resizeAll:		resizeAll		// method - no parameters
          	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
          	,	addOpenBtn:		addOpenBtn		// utility - ditto
          	,	addCloseBtn:	addCloseBtn		// utility - ditto
          	,	addPinBtn:		addPinBtn		// utility - ditto
          	,	allowOverflow:	allowOverflow	// utility - pass calling element
          	,	resetOverflow:	resetOverflow	// utility - ditto
          	,	cssWidth:		cssW
          	,	cssHeight:		cssH
          	};
          
          }
          })( jQuery );
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        33. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bTODO\b and was detected 7 times, the first in the element starting with: " * @TODO May need to add additional logic to handle more browser/doctype variations? ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (379 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 82920
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"82920-1230357900000"
          Last-Modified: Sat, 27 Dec 2008 06:05:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (82920 bytes)
          /*
           * jquery.layout 1.2.0
           *
           * Copyright (c) 2008 
           *   Fabrizio Balliano (http://www.fabrizioballiano.net)
           *   Kevin Dalman (http://allpro.net)
           *
           * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
           * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
           *
           * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
           * $Rev: 203 $
           * 
           * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
           */
          (function($) {
          
          $.fn.layout = function (opts) {
          
          /*
           * ###########################
           *   WIDGET CONFIG & OPTIONS
           * ###########################
           */
          
          	// DEFAULTS for options
          	var 
          		prefix = "ui-layout-" // prefix for ALL selectors and classNames
          	,	defaults = { //	misc default values
          			paneClass:				prefix+"pane"		// ui-layout-pane
          		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
          		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
          		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
          		,	buttonClass:			prefix+"button"		// ui-layout-button
          		,	contentSelector:		"."+prefix+"content"// ui-layout-content
          		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
          		}
          	;
          
          	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
          	var options = {
          		name:						""			// FUTURE REFERENCE - not used right now
          	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
          	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
          			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
          		,	closable:				true		// pane can open & close
          		,	resizable:				true		// when open, pane can be resized 
          		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
          		//,	paneSelector:			[ ]			// MUST be pane-specific!
          		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
          		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
          		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
          		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
          		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
          		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
          		,	resizerDragOpacity:		1			// option for ui.draggable
          		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
          		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
          		//,	size:					100			// inital size of pane - defaults are set 'per pane'
          		,	minSize:				0			// when manually resizing a pane
          		,	maxSize:				0			// ditto, 0 = no limit
          		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
          		,	spacing_closed:			6			// ditto - when pane is 'closed'
          		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
          		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
          		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
          		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
          		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
          		,	togglerTip_closed:		"Open"		// ditto
          		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
          		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
          		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
          		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
          		,	slideTrigger_close:		"mouseout"	// click, mouseout
          		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
          		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
          		,	togglerContent_closed:	""			// ditto
          		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
          		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
          		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
          		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
          		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
          		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
          		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
          		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
          		,	initClosed:				false		// true = init pane as 'closed'
          		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
          		
          		/*	callback options do not have to be set - listed here for reference only
          		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
          		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
          		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
          		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
          		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
          		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
          		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
          		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
          		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
          		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
          		*/
          		}
          	,	north: {
          			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
          		,	size:					"auto"
          		,	resizerCursor:			"n-resize"
          		}
          	,	south: {
          			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
          		,	size:					"auto"
          		,	resizerCursor:			"s-resize"
          		}
          	,	east: {
          			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
          		,	size:					200
          		,	resizerCursor:			"e-resize"
          		}
          	,	west: {
          			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
          		,	size:					200
          		,	resizerCursor:			"w-resize"
          		}
          	,	center: {
          			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
          		}
          
          	};
          
          
          	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
          		slide:	{
          			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	drop:	{
          			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	scale:	{
          			all:	{ duration:  "fast"	}
          		}
          	};
          
          
          	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
          	var config = {
          		allPanes:		"north,south,east,west,center"
          	,	borderPanes:	"north,south,east,west"
          	,	zIndex: { // set z-index values here
          			resizer_normal:	1		// normal z-index for resizer-bars
          		,	pane_normal:	2		// normal z-index for panes
          		,	mask:			4		// overlay div used to mask pane(s) during resizing
          		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
          		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
          		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
          		}
          	,	resizers: {
          			cssReq: {
          				position: 	"absolute"
          			,	padding: 	0
          			,	margin: 	0
          			,	fontSize:	"1px"
          			,	textAlign:	"left" // to counter-act "center" alignment!
          			,	overflow: 	"hidden" // keep toggler button from overflowing
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#DDD"
          			,	border:		"none"
          			}
          		}
          	,	togglers: {
          			cssReq: {
          				position: 	"absolute"
          			,	display: 	"block"
          			,	padding: 	0
          			,	margin: 	0
          			,	overflow:	"hidden"
          			,	textAlign:	"center"
          			,	fontSize:	"1px"
          			,	cursor: 	"pointer"
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#AAA"
          			}
          		}
          	,	content: {
          			cssReq: {
          				overflow:	"auto"
          			}
          		,	cssDef: {}
          		}
          	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
          			cssReq: {
          				position: 	"absolute"
          			,	margin:		0
          			,	zIndex: 	2
          			}
          		,	cssDef: {
          				padding:	"10px"
          			,	background:	"#FFF"
          			,	border:		"1px solid #BBB"
          			,	overflow:	"auto"
          			}
          		}
          	,	north: {
          			edge:			"top"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		0
          			,	bottom: 	"auto"
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	south: {
          			edge:			"bottom"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		"auto"
          			,	bottom: 	0
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	east: {
          			edge:			"right"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		"auto"
          			,	right: 		0
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	west: {
          			edge:			"left"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		0
          			,	right: 		"auto"
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	center: {
          			dir:			"center"
          		,	cssReq: {
          				left: 		"auto" // DYNAMIC
          			,	right: 		"auto" // DYNAMIC
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			,	width: 		"auto"
          			}
          		}
          	};
          
          
          	// DYNAMIC DATA
          	var state = {
          		// generate random 'ID#' to identify layout - used to create global namespace for timers
          		id:			Math.floor(Math.random() * 10000)
          	,	container:	{}
          	,	north:		{}
          	,	south:		{}
          	,	east:		{}
          	,	west:		{}
          	,	center:		{}
          	};
          
          
          	var 
          		altEdge = {
          			top:	"bottom"
          		,	bottom: "top"
          		,	left:	"right"
          		,	right:	"left"
          		}
          	,	altSide = {
          			north:	"south"
          		,	south:	"north"
          		,	east: 	"west"
          		,	west: 	"east"
          		}
          	;
          
          
          /*
           * ###########################
           *  INTERNAL HELPER FUNCTIONS
           * ###########################
           */
          
          	/**
          	 * isStr
          	 *
          	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
          	 */
          	var isStr = function (o) {
          		if (typeof o == "string")
          			return true;
          		else if (typeof o == "object") {
          			try {
          				var match = o.constructor.toString().match(/string/i); 
          				return (match !== null);
          			} catch (e) {} 
          		}
          		return false;
          	};
          
          	/**
          	 * str
          	 *
          	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
          	 *  else returns the original object
          	 */
          	var str = function (o) {
          		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
          		else return o;
          	};
          
          	/**
          	 * min / max
          	 *
          	 * Alias for Math.min/.max to simplify coding
          	 */
          	var min = function (x,y) { return Math.min(x,y); };
          	var max = function (x,y) { return Math.max(x,y); };
          
          	/**
          	 * transformData
          	 *
          	 * Processes the options passed in and transforms them into the format used by layout()
          	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
          	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
          	 * To update effects, options MUST use nested-keys format, with an effects key
          	 *
          	 * @callers  initOptions()
          	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
          	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
          	 */
          	var transformData = function (d) {
          		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
          		d = d || {};
          		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
          			json = $.extend( json, d ); // already in json format - add to base keys
          		else
          			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
          			$.each( d, function (key,val) {
          				a = key.split("__");
          				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
          			});
          		return json;
          	};
          
          	/**
          	 * setFlowCallback
          	 *
          	 * Set an INTERNAL callback to avoid simultaneous animation
          	 * Runs only if needed and only if all callbacks are not 'already set'!
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var setFlowCallback = function (action, pane, param) {
          		var
          			cb = action +","+ pane +","+ (param ? 1 : 0)
          		,	cP, cbPane
          		;
          		$.each(c.borderPanes.split(","), function (i,p) {
          			if (c[p].isMoving) {
          				bindCallback(p); // TRY to bind a callback
          				return false; // BREAK
          			}
          		});
          
          		function bindCallback (p, test) {
          			cP = c[p];
          			if (!cP.doCallback) {
          				cP.doCallback = true;
          				cP.callback = cb;
          			}
          			else { // try to 'chain' this callback
          				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
          				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
          					bindCallback (cpPane, true); // RECURSE
          			}
          		}
          	};
          
          	/**
          	 * execFlowCallback
          	 *
          	 * RUN the INTERNAL callback for this pane - if one exists
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var execFlowCallback = function (pane) {
          		var cP = c[pane];
          
          		// RESET flow-control flaGs
          		c.isLayoutBusy = false;
          		delete cP.isMoving;
          		if (!cP.doCallback || !cP.callback) return;
          
          		cP.doCallback = false; // RESET logic flag
          
          		// EXECUTE the callback
          		var
          			cb = cP.callback.split(",")
          		,	param = (cb[2] > 0 ? true : false)
          		;
          		if (cb[0] == "open")
          			open( cb[1], param  );
          		else if (cb[0] == "close")
          			close( cb[1], param );
          
          		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
          	};
          
          	/**
          	 * execUserCallback
          	 *
          	 * Executes a Callback function after a trigger event, like resize, open or close
          	 *
          	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
          	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
          	 */
          	var execUserCallback = function (pane, v_fn) {
          		if (!v_fn) return;
          		var fn;
          		try {
          			if (typeof v_fn == "function")
          				fn = v_fn;	
          			else if (typeof v_fn != "string")
          				return;
          			else if (v_fn.indexOf(",") > 0) {
          				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
          				var
          					args = v_fn.split(",")
          				,	fn = eval(args[0])
          				;
          				if (typeof fn=="function" && args.length > 1)
          					return fn(args[1]); // pass the argument parsed from 'list'
          			}
          			else // just the name of an external function?
          				fn = eval(v_fn);
          
          			if (typeof fn=="function")
          				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
          				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
          		}
          		catch (ex) {}
          	};
          
          	/**
          	 * cssNum
          	 *
          	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
          	 *
          	 * @callers  Called by many methods
          	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
          	 * @param String  property  The name of the CSS property, eg: top, width, etc.
          	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
          	 */
          	var cssNum = function ($E, prop) {
          		var
          			val = 0
          		,	hidden = false
          		,	visibility = ""
          		;
          		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
          			if ($.curCSS($E[0], "display", true) == "none") {
          				hidden = true;
          				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
          				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
          			}
          		}
          
          		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
          
          		if (hidden) { // WAS hidden, so put back the way it was
          			$E.css({ display: "none" });
          			if (visibility && visibility != "hidden")
          				$E.css({ visibility: visibility }); // reset 'visibility'
          		}
          
          		return val;
          	};
          
          	/**
          	 * cssW / cssH / cssSize
          	 *
          	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
          	 *
          	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
          	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
          	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
          	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
          	 *
          	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
          	 */
          	var cssW = function (e, outerWidth) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerWidth <= 0)
          			return 0;
          		else if (!(outerWidth>0))
          			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
          
          		if (!$.boxModel)
          			return outerWidth;
          
          		else // strip border and padding size from outerWidth to get CSS Width
          			return outerWidth
          				- cssNum($E, "paddingLeft")		
          				- cssNum($E, "paddingRight")
          				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
          				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
          			;
          	};
          	var cssH = function (e, outerHeight) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerHeight <= 0)
          			return 0;
          		else if (!(outerHeight>0))
          			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
          
          		if (!$.boxModel)
          			return outerHeight;
          
          		else // strip border and padding size from outerHeight to get CSS Height
          			return outerHeight
          				- cssNum($E, "paddingTop")
          				- cssNum($E, "paddingBottom")
          				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
          				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
          			;
          	};
          	var cssSize = function (pane, outerSize) {
          		if (c[pane].dir=="horz") // pane = north or south
          			return cssH(pane, outerSize);
          		else // pane = east or west
          			return cssW(pane, outerSize);
          	};
          
          	/**
          	 * getPaneSize
          	 *
          	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
          	 *
          	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
          	 */
          	var getPaneSize = function (pane, inclSpace) {
          		var 
          			$P	= $Ps[pane]
          		,	o	= options[pane]
          		,	s	= state[pane]
          		,	oSp	= (inclSpace ? o.spacing_open : 0)
          		,	cSp	= (inclSpace ? o.spacing_closed : 0)
          		;
          		if (!$P || s.isHidden)
          			return 0;
          		else if (s.isClosed || (s.isSliding && inclSpace))
          			return cSp;
          		else if (c[pane].dir == "horz")
          			return $P.outerHeight() + oSp;
          		else // dir == "vert"
          			return $P.outerWidth() + oSp;
          	};
          
          	var setPaneMinMaxSizes = function (pane) {
          		var 
          			d				= cDims
          		,	edge			= c[pane].edge
          		,	dir				= c[pane].dir
          		,	o				= options[pane]
          		,	s				= state[pane]
          		,	$P				= $Ps[pane]
          		,	$altPane		= $Ps[ altSide[pane] ]
          		,	paneSpacing		= o.spacing_open
          		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
          		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
          		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
          		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
          		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
          		,	minSize			= s.minSize || 0
          		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
          		,	minPos, maxPos	// used to set resizing limits
          		;
          		switch (pane) {
          			case "north":	minPos = d.offsetTop + minSize;
          							maxPos = d.offsetTop + maxSize;
          							break;
          			case "west":	minPos = d.offsetLeft + minSize;
          							maxPos = d.offsetLeft + maxSize;
          							break;
          			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
          							maxPos = d.offsetTop + d.innerHeight - minSize;
          							break;
          			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
          							maxPos = d.offsetLeft + d.innerWidth - minSize;
          							break;
          		}
          		// save data to pane-state
          		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
          	};
          
          	/**
          	 * getPaneDims
          	 *
          	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
          	 *
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
          	 */
          	var getPaneDims = function () {
          		var d = {
          			top:	getPaneSize("north", true) // true = include 'spacing' value for p
          		,	bottom:	getPaneSize("south", true)
          		,	left:	getPaneSize("west", true)
          		,	right:	getPaneSize("east", true)
          		,	width:	0
          		,	height:	0
          		};
          
          		with (d) {
          			width 	= cDims.innerWidth - left - right;
          			height 	= cDims.innerHeight - bottom - top;
          			// now add the 'container border/padding' to get final positions - relative to the container
          			top		+= cDims.top;
          			bottom	+= cDims.bottom;
          			left	+= cDims.left;
          			right	+= cDims.right;
          		}
          
          		return d;
          	};
          
          
          	/**
          	 * getElemDims
          	 *
          	 * Returns data for setting size of an element (container or a pane).
          	 *
          	 * @callers  create(), onWindowResize() for container, plus others for pane
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
          	 */
          	var getElemDims = function ($E) {
          		var
          			d = {} // dimensions hash
          		,	e, b, p // edge, border, padding
          		;
          
          		$.each("Left,Right,Top,Bottom".split(","), function () {
          			e = str(this);
          			b = d["border" +e] = cssNum($E, "border"+e+"Width");
          			p = d["padding"+e] = cssNum($E, "padding"+e);
          			d["offset" +e] = b + p; // total offset of content from outer edge
          			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
          			if ($E == $Container)
          				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
          		});
          
          		d.innerWidth  = d.outerWidth  = $E.outerWidth();
          		d.innerHeight = d.outerHeight = $E.outerHeight();
          		if ($.boxModel) {
          			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
          			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
          		}
          
          		return d;
          	};
          
          
          	var setTimer = function (pane, action, fn, ms) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) return; // timer already set!
          		else Timers[name] = setTimeout(fn, ms);
          	};
          
          	var clearTimer = function (pane, action) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) {
          			clearTimeout( Timers[name] );
          			delete Timers[name];
          			return true;
          		}
          		else
          			return false;
          	};
          
          
          /*
           * ###########################
           *   INITIALIZATION METHODS
           * ###########################
           */
          
          	/**
          	 * create
          	 *
          	 * Initialize the layout - called automatically whenever an instance of layout is created
          	 *
          	 * @callers  NEVER explicity called
          	 * @returns  An object pointer to the instance created
          	 */
          	var create = function () {
          		// initialize config/options
          		initOptions();
          
          		// initialize all objects
          		initContainer();	// set CSS as needed and init state.container dimensions
          		initPanes();		// size & position all panes
          		initHandles();		// create and position all resize bars & togglers buttons
          		initResizable();	// activate resizing on all panes where resizable=true
          		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
          
          		if (options.scrollToBookmarkOnLoad)
          			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
          
          		// bind hotkey function - keyDown - if required
          		initHotkeys();
          
          		// bind resizeAll() for 'this layout instance' to window.resize event
          		$(window).resize(function () {
          			var timerID = "timerLayout_"+state.id;
          			if (window[timerID]) clearTimeout(window[timerID]);
          			window[timerID] = null;
          			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
          				window[timerID] = setTimeout(resizeAll, 100);
          			else // most other browsers have a built-in delay before firing the resize event
          				resizeAll(); // resize all layout elements NOW!
          		});
          	};
          
          	/**
          	 * initContainer
          	 *
          	 * Validate and initialize container CSS and events
          	 *
          	 * @callers  create()
          	 */
          	var initContainer = function () {
          		try { // format html/body if this is a full page layout
          			if ($Container[0].tagName == "BODY") {
          				$("html").css({
          					height:		"100%"
          				,	overflow:	"hidden"
          				});
          				$("body").css({
          					position:	"relative"
          				,	height:		"100%"
          				,	overflow:	"hidden"
          				,	margin:		0
          				,	padding:	0		// TODO: test whether body-padding could be handled?
          				,	border:		"none"	// a body-border creates problems because it cannot be measured!
          				});
          			}
          			else { // set required CSS - overflow and position
          				var
          					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
          				,	p	= $Container.css("position")
          				,	h	= $Container.css("height")
          				;
          				// if this is a NESTED layout, then outer-pane ALREADY has position and height
          				if (!$Container.hasClass("ui-layout-pane")) {
          					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
          						CSS.position = "relative"; // container MUST have a 'position'
          					if (!h || h=="auto")
          						CSS.height = "100%"; // container MUST have a 'height'
          				}
          				$Container.css( CSS );
          			}
          		} catch (ex) {}
          
          		// get layout-container dimensions (updated when necessary)
          		cDims = state.container = getElemDims( $Container ); // update data-pointer too
          	};
          
          	/**
          	 * initHotkeys
          	 *
          	 * Bind layout hotkeys - if options enabled
          	 *
          	 * @callers  create()
          	 */
          	var initHotkeys = function () {
          		// bind keyDown to capture hotkeys, if option enabled for ANY pane
          		$.each(c.borderPanes.split(","), function (i,pane) {
          			var o = options[pane];
          			if (o.enableCursorHotkey || o.customHotkey) {
          				$(document).keydown( keyDown ); // only need to bind this ONCE
          				return false; // BREAK - binding was done
          			}
          		});
          	};
          
          	/**
          	 * initOptions
          	 *
          	 * Build final CONFIG and OPTIONS data
          	 *
          	 * @callers  create()
          	 */
          	var initOptions = function () {
          		// simplify logic by making sure passed 'opts' var has basic keys
          		opts = transformData( opts );
          
          		// update default effects, if case user passed key
          		if (opts.effects) {
          			$.extend( effects, opts.effects );
          			delete opts.effects;
          		}
          
          		// see if any 'global options' were specified
          		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
          			if (opts[key] !== undefined)
          				options[key] = opts[key];
          			else if (opts.defaults[key] !== undefined) {
          				options[key] = opts.defaults[key];
          				delete opts.defaults[key];
          			}
          		});
          
          		// remove any 'defaults' that MUST be set 'per-pane'
          		$.each("paneSelector,resizerCursor,customHotkey".split(","),
          			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
          		);
          
          		// now update options.defaults
          		$.extend( options.defaults, opts.defaults );
          		// make sure required sub-keys exist
          		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
          
          		// merge all config & options for the 'center' pane
          		c.center = $.extend( true, {}, c.defaults, c.center );
          		$.extend( options.center, opts.center );
          		// Most 'default options' do not apply to 'center', so add only those that DO
          		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
          		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
          			function (idx,key) { options.center[key] = o_Center[key]; }
          		);
          
          		var defs = options.defaults;
          
          		// create a COMPLETE set of options for EACH border-pane
          		$.each(c.borderPanes.split(","), function(i,pane) {
          			// apply 'pane-defaults' to CONFIG.PANE
          			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
          			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
          			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
          
          			// make sure we have base-classes
          			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
          			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
          			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
          
          			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
          			$.each(["_open","_close",""], function (i,n) { 
          				var
          					sName		= "fxName"+n
          				,	sSpeed		= "fxSpeed"+n
          				,	sSettings	= "fxSettings"+n
          				;
          				// recalculate fxName according to specificity rules
          				o[sName] =
          					opts[pane][sName]		// opts.west.fxName_open
          				||	opts[pane].fxName		// opts.west.fxName
          				||	opts.defaults[sName]	// opts.defaults.fxName_open
          				||	opts.defaults.fxName	// opts.defaults.fxName
          				||	o[sName]				// options.west.fxName_open
          				||	o.fxName				// options.west.fxName
          				||	defs[sName]				// options.defaults.fxName_open
          				||	defs.fxName				// options.defaults.fxName
          				||	"none"
          				;
          				// validate fxName to be sure is a valid effect
          				var fxName = o[sName];
          				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
          					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
          				// set vars for effects subkeys to simplify logic
          				var
          					fx = effects[fxName]	|| {} // effects.slide
          				,	fx_all	= fx.all		|| {} // effects.slide.all
          				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
          				;
          				// RECREATE the fxSettings[_open|_close] keys using specificity rules
          				o[sSettings] = $.extend(
          					{}
          				,	fx_all						// effects.slide.all
          				,	fx_pane						// effects.slide.west
          				,	defs.fxSettings || {}		// options.defaults.fxSettings
          				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
          				,	o.fxSettings				// options.west.fxSettings
          				,	o[sSettings]				// options.west.fxSettings_open
          				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
          				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
          				,	opts[pane].fxSettings		// opts.west.fxSettings
          				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
          				);
          				// recalculate fxSpeed according to specificity rules
          				o[sSpeed] =
          					opts[pane][sSpeed]		// opts.west.fxSpeed_open
          				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
          				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
          				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
          				||	o[sSpeed]				// options.west.fxSpeed_open
          				||	o[sSettings].duration	// options.west.fxSettings_open.duration
          				||	o.fxSpeed				// options.west.fxSpeed
          				||	o.fxSettings.duration	// options.west.fxSettings.duration
          				||	defs.fxSpeed			// options.defaults.fxSpeed
          				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
          				||	fx_pane.duration		// effects.slide.west.duration
          				||	fx_all.duration			// effects.slide.all.duration
          				||	"normal"				// DEFAULT
          				;
          				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
          			});
          		});
          	};
          
          	/**
          	 * initPanes
          	 *
          	 * Initialize module objects, styling, size and position for all panes
          	 *
          	 * @callers  create()
          	 */
          	var initPanes = function () {
          		// NOTE: do north & south FIRST so we can measure their height - do center LAST
          		$.each(c.allPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	fx		= s.fx
          			,	dir		= c[pane].dir
          			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
          			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
          			,	minSize	= o.minSize || 1
          			,	maxSize	= o.maxSize || 9999
          			,	spacing	= o.spacing_open || 0
          			,	sel		= o.paneSelector
          			,	isIE6	= ($.browser.msie && $.browser.version < 7)
          			,	CSS		= {}
          			,	$P, $C
          			;
          			$Cs[pane] = false; // init
          
          			if (sel.substr(0,1)==="#") // ID selector
          				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
          				$P = $Ps[pane] = $Container.find(sel+":first");
          			else { // class or other selector
          				$P = $Ps[pane] = $Container.children(sel+":first");
          				// look for the pane nested inside a 'form' element
          				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
          			}
          
          			if (!$P.length) {
          				$Ps[pane] = false; // logic
          				return true; // SKIP to next
          			}
          
          			// add basic classes & attributes
          			$P
          				.attr("pane", pane) // add pane-identifier
          				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
          			;
          
          			// init pane-logic vars, etc.
          			if (pane != "center") {
          				s.isClosed  = false; // true = pane is closed
          				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
          				s.isResizing= false; // true = pane is in process of being resized
          				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
          				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
          				// create special keys for internal use
          				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
          			}
          
          			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
          			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
          			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
          			CSS = {};	// reset var
          
          			// set css-position to account for container borders & padding
          			switch (pane) {
          				case "north": 	CSS.top 	= cDims.top;
          								CSS.left 	= cDims.left;
          								CSS.right	= cDims.right;
          								break;
          				case "south": 	CSS.bottom	= cDims.bottom;
          								CSS.left 	= cDims.left;
          								CSS.right 	= cDims.right;
          								break;
          				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
          								break;
          				case "east": 	CSS.right 	= cDims.right; // ditto
          								break;
          				case "center":	// top, left, width & height set by sizeMidPanes()
          			}
          
          			if (dir == "horz") { // north or south pane
          				if (size === 0 || size == "auto") {
          					$P.css({ height: "auto" });
          					size = $P.outerHeight();
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerHeight - spacing);
          				CSS.height = max(1, cssH(pane, size));
          				s.size = size; // update state
          				// make sure minSize is sufficient to avoid errors
          				s.maxSize = maxSize; // init value
          				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
          				// handle IE6
          				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
          				$P.css(CSS); // apply size & position
          			}
          			else if (dir == "vert") { // east or west pane
          				if (size === 0 || size == "auto") {
          					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
          					size = $P.outerWidth();
          					$P.css({ float: "none" }); // RESET
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerWidth - spacing);
          				CSS.width = max(1, cssW(pane, size));
          				s.size = size; // update state
          				s.maxSize = maxSize; // init value
          				// make sure minSize is sufficient to avoid errors
          				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
          				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
          				sizeMidPanes(pane, null, true); // true = onInit
          			}
          			else if (pane == "center") {
          				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
          				sizeMidPanes("center", null, true); // true = onInit
          			}
          
          			// close or hide the pane if specified in settings
          			if (o.initClosed && o.closable) {
          				$P.hide().addClass("closed");
          				s.isClosed = true;
          			}
          			else if (o.initHidden || o.initClosed) {
          				hide(pane, true); // will be completely invisible - no resizer or spacing
          				s.isHidden = true;
          			}
          			else
          				$P.addClass("open");
          
          			// check option for auto-handling of pop-ups & drop-downs
          			if (o.showOverflowOnHover)
          				$P.hover( allowOverflow, resetOverflow );
          
          			/*
          			 *	see if this pane has a 'content element' that we need to auto-size
          			 */
          			if (o.contentSelector) {
          				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
          				if (!$C.length) {
          					$Cs[pane] = false;
          					return true; // SKIP to next
          				}
          				$C.css( c.content.cssReq );
          				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
          				// NO PANE-SCROLLING when there is a content-div
          				$P.css({ overflow: "hidden" });
          			}
          		});
          	};
          
          	/**
          	 * initHandles
          	 *
          	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
          	 *
          	 * @callers  create()
          	 */
          	var initHandles = function () {
          		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	rClass	= o.resizerClass
          			,	tClass	= o.togglerClass
          			,	$P		= $Ps[pane]
          			;
          			$Rs[pane] = false; // INIT
          			$Ts[pane] = false;
          
          			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
          
          			var 
          				edge	= c[pane].edge
          			,	isOpen	= $P.is(":visible")
          			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
          			,	_pane	= "-"+ pane // used for classNames
          			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
          			,	$R, $T
          			;
          			// INIT RESIZER BAR
          			$R = $Rs[pane] = $("<span></span>");
          	
          			if (isOpen && o.resizable)
          				; // this is handled by initResizable
          			else if (!isOpen && o.slidable)
          				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
          	
          			$R
          				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
          				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
          				.attr("resizer", pane) // so we can read this from the resizer
          				.css(c.resizers.cssReq) // add base/required styles
          				// POSITION of resizer bar - allow for container border & padding
          				.css(edge, cDims[edge] + getPaneSize(pane))
          				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
          				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
          				.appendTo($Container) // append DIV to container
          			;
          			 // ADD VISUAL STYLES
          			if (o.applyDefaultStyles)
          				$R.css(c.resizers.cssDef);
          
          			if (o.closable) {
          				// INIT COLLAPSER BUTTON
          				$T = $Ts[pane] = $("<div></div>");
          				$T
          					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
          					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
          					.css(c.togglers.cssReq) // add base/required styles
          					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
          					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
          					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
          					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
          					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
          					.appendTo($R) // append SPAN to resizer DIV
          				;
          
          				// ADD INNER-SPANS TO TOGGLER
          				if (o.togglerContent_open) // ui-layout-open
          					$("<span>"+ o.togglerContent_open +"</span>")
          						.addClass("content content-open")
          						.css("display", s.isClosed ? "none" : "block")
          						.appendTo( $T )
          					;
          				if (o.togglerContent_closed) // ui-layout-closed
          					$("<span>"+ o.togglerContent_closed +"</span>")
          						.addClass("content content-closed")
          						.css("display", s.isClosed ? "block" : "none")
          						.appendTo( $T )
          					;
          
          				 // ADD BASIC VISUAL STYLES
          				if (o.applyDefaultStyles)
          					$T.css(c.togglers.cssDef);
          
          				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          			}
          
          		});
          
          		// SET ALL HANDLE SIZES & LENGTHS
          		sizeHandles("all", true); // true = onInit
          	};
          
          	/**
          	 * initResizable
          	 *
          	 * Add resize-bars to all panes that specify it in options
          	 *
          	 * @dependancies  $.fn.resizable - will abort if not found
          	 * @callers  create()
          	 */
          	var initResizable = function () {
          		var
          			draggingAvailable = (typeof $.fn.draggable == "function")
          		,	minPosition, maxPosition, edge // set in start()
          		;
          
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			;
          			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
          				o.resizable = false;
          				return true; // skip to next
          			}
          
          			var 
          				rClass				= o.resizerClass
          			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
          			,	dragClass			= rClass+"-drag"			// resizer-drag
          			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
          			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
          			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
          			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
          			,	draggingClassSet	= false 					// logic var
          			,	$P 					= $Ps[pane]
          			,	$R					= $Rs[pane]
          			;
          
          			if (!s.isClosed)
          				$R
          					.attr("title", o.resizerTip)
          					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
          				;
          
          			$R.draggable({
          				containment:	$Container[0] // limit resizing to layout container
          			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
          			,	delay:			200
          			,	distance:		1
          			//	basic format for helper - style it using class: .ui-draggable-dragging
          			,	helper:			"clone"
          			,	opacity:		o.resizerDragOpacity
          			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
          			,	zIndex:			c.zIndex.resizing
          
          			,	start: function (e, ui) {
          					// onresize_start callback - will CANCEL hide if returns false
          					// TODO: CONFIRM that dragging can be cancelled like this???
          					if (false === execUserCallback(pane, o.onresize_start)) return false;
          
          					s.isResizing = true; // prevent pane from closing while resizing
          					clearTimer(pane, "closeSlider"); // just in case already triggered
          
          					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
          					draggingClassSet = false; // reset logic var - see drag()
          
          					// SET RESIZING LIMITS - used in drag()
          					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
          					setPaneMinMaxSizes(pane); // update pane-state
          					s.minPosition -= resizerWidth;
          					s.maxPosition -= resizerWidth;
          					edge = (c[pane].dir=="horz" ? "top" : "left");
          
          					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
          					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
          						$('<div class="ui-layout-mask"/>')
          							.css({
          								background:	"#fff"
          							,	opacity:	"0.001"
          							,	zIndex:		9
          							,	position:	"absolute"
          							,	width:		this.offsetWidth+"px"
          							,	height:		this.offsetHeight+"px"
          							})
          							.css($(this).offset()) // top & left
          							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
          						;
          					});
          				}
          
          			,	drag: function (e, ui) {
          					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
          						$(".ui-draggable-dragging")
          							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
          							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
          						;
          						draggingClassSet = true;
          						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
          						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
          					}
          					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
          					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
          					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
          				}
          
          			,	stop: function (e, ui) {
          					var 
          						dragPos	= ui.position
          					,	resizerPos
          					,	newSize
          					;
          					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
          	
          					switch (pane) {
          						case "north":	resizerPos = dragPos.top; break;
          						case "west":	resizerPos = dragPos.left; break;
          						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
          						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
          					}
          					// remove container margin from resizer position to get the pane size
          					newSize = resizerPos - cDims[ c[pane].edge ];
          
          					sizePane(pane, newSize);
          
          					// UN-MASK PANES MASKED IN drag.start
          					$("div.ui-layout-mask").remove(); // Remove iframe masks	
          
          					s.isResizing = false;
          				}
          
          			});
          		});
          	};
          
          
          
          /*
           * ###########################
           *       ACTION METHODS
           * ###########################
           */
          
          	/**
          	 * hide / show
          	 *
          	 * Completely 'hides' a pane, including its spacing - as if it does not exist
          	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
          	 *
          	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
          	 */
          	var hide = function (pane, onInit) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onhide_start)) return;
          
          		s.isSliding = false; // just in case
          
          		// now hide the elements
          		if ($R) $R.hide(); // hide resizer-bar
          		if (onInit || s.isClosed) {
          			s.isClosed = true; // to trigger open-animation on show()
          			s.isHidden  = true;
          			$P.hide(); // no animation when loading page
          			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          			execUserCallback(pane, o.onhide_end || o.onhide);
          		}
          		else {
          			s.isHiding = true; // used by onclose
          			close(pane, false); // adjust all panes to fit
          			//s.isHidden  = true; - will be set by close - if not cancelled
          		}
          	};
          
          	var show = function (pane, openPane) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onshow_start)) return;
          
          		s.isSliding = false; // just in case
          		s.isShowing = true; // used by onopen/onclose
          		//s.isHidden  = false; - will be set by open/close - if not cancelled
          
          		// now show the elements
          		if ($R && o.spacing_open > 0) $R.show();
          		if (openPane === false)
          			close(pane, true); // true = force
          		else
          			open(pane); // adjust all panes to fit
          	};
          
          
          	/**
          	 * toggle
          	 *
          	 * Toggles a pane open/closed by calling either open or close
          	 *
          	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
          	 */
          	var toggle = function (pane) {
          		var s = state[pane];
          		if (s.isHidden)
          			show(pane); // will call 'open' after unhiding it
          		else if (s.isClosed)
          			open(pane);
          		else
          			close(pane);
          	};
          
          	/**
          	 * close
          	 *
          	 * Close the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being closed, ie: north, south, east, or west
          	 */
          	var close = function (pane, force, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_sliding= "-sliding"
          		,	_closed	= "-closed"
          		// 	transfer logic vars to temp vars
          		,	isShowing = s.isShowing
          		,	isHiding = s.isHiding
          		;
          		// now clear the logic vars
          		delete s.isShowing;
          		delete s.isHiding;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!force && s.isClosed && !isShowing) return; // already closed
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("close", pane, force); // set a callback for this action, if possible
          			return; // ABORT 
          		}
          
          		// onclose_start callback - will CANCEL hide if returns false
          		// SKIP if just 'showing' a hidden pane as 'closed'
          		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		s.isClosed = true;
          		// update isHidden BEFORE sizing panes
          		if (isHiding) s.isHidden = true;
          		else if (isShowing) s.isHidden = false;
          
          		// sync any 'pin buttons'
          		syncPinBtns(pane, false);
          
          		// resize panes adjacent to this one
          		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          
          		// if this pane has a resizer bar, move it now
          		if ($R) {
          			$R
          				.css(edge, cDims[edge]) // move the resizer bar
          				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
          				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
          				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
          			;
          			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
          			if (o.resizable)
          				$R
          					.draggable("disable")
          					.css("cursor", "default")
          					.attr("title","")
          				;
          			// if pane has a toggler button, adjust that too
          			if ($T) {
          				$T
          					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
          					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
          					.attr("title", o.togglerTip_closed) // may be blank
          				;
          			}
          			sizeHandles(); // resize 'length' and position togglers for adjacent panes
          		}
          
          		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
          		if (doFX) {
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
          				lockPaneForFX(pane, false); // undo
          				if (!s.isClosed) return; // pane was opened before animation finished!
          				close_2();
          			});
          		}
          		else {
          			$P.hide(); // just hide pane NOW
          			close_2();
          		}
          
          		// SUBROUTINE
          		function close_2 () {
          			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          
          			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
          			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
          			// onhide OR onshow callback
          			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
          			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          
          	/**
          	 * open
          	 *
          	 * Open the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being opened, ie: north, south, east, or west
          	 */
          	var open = function (pane, slide, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_closed	= "-closed"
          		,	_sliding= "-sliding"
          		// 	transfer logic var to temp var
          		,	isShowing = s.isShowing
          		;
          		// now clear the logic var
          		delete s.isShowing;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!s.isClosed && !s.isSliding) return; // already open
          
          		// pane can ALSO be unhidden by just calling show(), so handle this scenario
          		if (s.isHidden && !isShowing) {
          			show(pane, true);
          			return;
          		}
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
          			return; // ABORT
          		}
          
          		// onopen_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onopen_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		// 'PIN PANE' - stop sliding
          		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
          			bindStopSlidingEvents(pane, false); // will set isSliding=false
          
          		s.isClosed = false;
          		// update isHidden BEFORE sizing panes
          		if (isShowing) s.isHidden = false;
          
          		// Container size may have changed - shrink the pane if now 'too big'
          		setPaneMinMaxSizes(pane); // update pane-state
          		if (s.size > s.maxSize) // pane is too big! resize it before opening
          			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
          
          		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
          
          		if (doFX) { // ANIMATE
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
          				lockPaneForFX(pane, false); // undo
          				if (s.isClosed) return; // pane was closed before animation finished!
          				open_2(); // continue
          			});
          		}
          		else {// no animation
          			$P.show();	// just show pane and...
          			open_2();	// continue
          		}
          
          		// SUBROUTINE
          		function open_2 () {
          			// NOTE: if isSliding, then other panes are NOT 'resized'
          			if (!s.isSliding) // resize all panes adjacent to this one
          				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
          
          			// if this pane has a toggler, move it now
          			if ($R) {
          				$R
          					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
          					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
          					.addClass( rClass+_open +" "+ rClass+_pane+_open )
          					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
          				;
          				if (o.resizable)
          					$R
          						.draggable("enable")
          						.css("cursor", o.resizerCursor)
          						.attr("title", o.resizerTip)
          					;
          				else
          					$R.css("cursor", "default"); // n-resize, s-resize, etc
          				// if pane also has a toggler button, adjust that too
          				if ($T) {
          					$T
          						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
          						.addClass( tClass+_open +" "+ tClass+_pane+_open )
          						.attr("title", o.togglerTip_open) // may be blank
          					;
          				}
          				sizeHandles("all"); // resize resizer & toggler sizes for all panes
          			}
          
          			// resize content every time pane opens - to be sure
          			sizeContent(pane);
          
          			// sync any 'pin buttons'
          			syncPinBtns(pane, !s.isSliding);
          
          			// onopen callback
          			execUserCallback(pane, o.onopen_end || o.onopen);
          
          			// onshow callback
          			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          	
          
          	/**
          	 * lockPaneForFX
          	 *
          	 * Must set left/top on East/South panes so animation will work properly
          	 *
          	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
          	 * @param Boolean  doLock  true = set left/top, false = remove
          	 */
          	var lockPaneForFX = function (pane, doLock) {
          		var $P = $Ps[pane];
          		if (doLock) {
          			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
          			if (pane=="south")
          				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
          			else if (pane=="east")
          				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
          		}
          		else {
          			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
          			if (pane=="south")
          				$P.css({ top: "auto" });
          			else if (pane=="east")
          				$P.css({ left: "auto" });
          		}
          	};
          
          
          	/**
          	 * bindStartSlidingEvent
          	 *
          	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
          	 *
          	 * @callers  open(), close()
          	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
          	 * @param Boolean  enable  Enable or Disable sliding?
          	 */
          	var bindStartSlidingEvent = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	$R		= $Rs[pane]
          		,	trigger	= o.slideTrigger_open
          		;
          		if (!$R || !o.slidable) return;
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
          		$R
          			// add or remove trigger event
          			[enable ? "bind" : "unbind"](trigger, slideOpen)
          			// set the appropriate cursor & title/tip
          			.css("cursor", (enable ? o.sliderCursor: "default"))
          			.attr("title", (enable ? o.sliderTip : ""))
          		;
          	};
          
          	/**
          	 * bindStopSlidingEvents
          	 *
          	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
          	 * Also increases zIndex when pane is sliding open
          	 * See bindStartSlidingEvent for code to control 'slide open'
          	 *
          	 * @callers  slideOpen(), slideClosed()
          	 * @param String  pane  The pane to process, 'north', 'south', etc.
          	 * @param Boolean  isOpen  Is pane open or closed?
          	 */
          	var bindStopSlidingEvents = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	s		= state[pane]
          		,	trigger	= o.slideTrigger_close
          		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          
          		s.isSliding = enable; // logic
          		clearTimer(pane, "closeSlider"); // just in case
          
          		// raise z-index when sliding
          		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
          		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
          
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
          
          		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
          		if (enable) { // BIND trigger events
          			$P.bind(trigger, slideClosed );
          			$R.bind(trigger, slideClosed );
          			if (trigger = "mouseout") {
          				$P.bind("mouseover", cancelMouseOut );
          				$R.bind("mouseover", cancelMouseOut );
          			}
          		}
          		else { // UNBIND trigger events
          			// TODO: why does unbind of a 'single function' not work reliably?
          			//$P[action](trigger, slideClosed );
          			$P.unbind(trigger);
          			$R.unbind(trigger);
          			if (trigger = "mouseout") {
          				//$P[action]("mouseover", cancelMouseOut );
          				$P.unbind("mouseover");
          				$R.unbind("mouseover");
          				clearTimer(pane, "closeSlider");
          			}
          		}
          
          		// SUBROUTINE for mouseout timer clearing
          		function cancelMouseOut (evt) {
          			clearTimer(pane, "closeSlider");
          			evt.stopPropagation();
          		}
          	};
          
          	var slideOpen = function () {
          		var pane = $(this).attr("resizer"); // attr added by initHandles
          		if (state[pane].isClosed) { // skip if already open!
          			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
          			open(pane, true); // true = slide - ie, called from here!
          		}
          	};
          
          	var slideClosed = function () {
          		var
          			$E = $(this)
          		,	pane = $E.attr("pane") || $E.attr("resizer")
          		,	o = options[pane]
          		,	s = state[pane]
          		;
          		if (s.isClosed || s.isResizing)
          			return; // skip if already closed OR in process of resizing
          		else if (o.slideTrigger_close == "click")
          			close_NOW(); // close immediately onClick
          		else // trigger = mouseout - use a delay
          			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
          
          		// SUBROUTINE for timed close
          		function close_NOW () {
          			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
          			if (!s.isClosed) close(pane); // skip if already closed!
          		}
          	};
          
          
          	/**
          	 * sizePane
          	 *
          	 * @callers  initResizable.stop()
          	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
          	 * @param Integer  newSize  The new size for this pane - will be validated
          	 */
          	var sizePane = function (pane, size) {
          		// TODO: accept "auto" as size, and size-to-fit pane content
          		var 
          			edge	= c[pane].edge
          		,	dir		= c[pane].dir
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          		// calculate 'current' min/max sizes
          		setPaneMinMaxSizes(pane); // update pane-state
          		// compare/update calculated min/max to user-options
          		s.minSize = max(s.minSize, o.minSize);
          		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
          		// validate passed size
          		size = max(size, s.minSize);
          		size = min(size, s.maxSize);
          		s.size = size; // update state
          
          		// move the resizer bar and resize the pane
          		$R.css( edge, size + cDims[edge] );
          		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
          
          		// resize all the adjacent panes, and adjust their toggler buttons
          		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
          		sizeHandles();
          		sizeContent(pane);
          		execUserCallback(pane, o.onresize_end || o.onresize);
          	};
          
          	/**
          	 * sizeMidPanes
          	 *
          	 * @callers  create(), open(), close(), onWindowResize()
          	 */
          	var sizeMidPanes = function (panes, overrideDims, onInit) {
          		if (!panes || panes == "all") panes = "east,west,center";
          
          		var d = getPaneDims();
          		if (overrideDims) $.extend( d, overrideDims );
          
          		$.each(panes.split(","), function() {
          			if (!$Ps[this]) return; // NO PANE - skip
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	hasRoom	= true
          			,	CSS		= {}
          			;
          
          			if (pane == "center") {
          				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
          				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
          				CSS.width  = max(1, cssW(pane, CSS.width));
          				CSS.height = max(1, cssH(pane, CSS.height));
          				hasRoom = (CSS.width > 1 && CSS.height > 1);
          				/*
          				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
          				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
          				 */
          				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
          					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
          					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
          				}
          			}
          			else { // for east and west, set only the height
          				CSS.top = d.top;
          				CSS.bottom = d.bottom;
          				CSS.height = max(1, cssH(pane, d.height));
          				hasRoom = (CSS.height > 1);
          			}
          
          			if (hasRoom) {
          				$P.css(CSS);
          				if (s.noRoom) {
          					s.noRoom = false;
          					if (s.isHidden) return;
          					else show(pane, !s.isClosed);
          					/* OLD CODE - keep until sure line above works right!
          					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
          					if ($R) $R.show();
          					*/
          				}
          				if (!onInit) {
          					sizeContent(pane);
          					execUserCallback(pane, o.onresize_end || o.onresize);
          				}
          			}
          			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
          				s.noRoom = true; // update state
          				if (s.isHidden) return;
          				if (onInit) { // skip onhide callback and other logic onLoad
          					$P.hide();
          					if ($R) $R.hide();
          				}
          				else hide(pane);
          			}
          		});
          	};
          
          
          	var sizeContent = function (panes) {
          		if (!panes || panes == "all") panes = c.allPanes;
          
          		$.each(panes.split(","), function() {
          			if (!$Cs[this]) return; // NO CONTENT - skip
          			var 
          				pane	= str(this)
          			,	ignore	= options[pane].contentIgnoreSelector
          			,	$P		= $Ps[pane]
          			,	$C		= $Cs[pane]
          			,	e_C		= $C[0]		// DOM element
          			,	height	= cssH($P);	// init to pane.innerHeight
          			;
          			$P.children().each(function() {
          				if (this == e_C) return; // Content elem - skip
          				var $E = $(this);
          				if (!ignore || !$E.is(ignore))
          					height -= $E.outerHeight();
          			});
          			if (height > 0)
          				height = cssH($C, height);
          			if (height < 1)
          				$C.hide(); // no room for content!
          			else
          				$C.css({ height: height }).show();
          		});
          	};
          
          
          	/**
          	 * sizeHandles
          	 *
          	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
          	 *
          	 * @callers  initHandles(), open(), close(), resizeAll()
          	 */
          	var sizeHandles = function (panes, onInit) {
          		if (!panes || panes == "all") panes = c.borderPanes;
          
          		$.each(panes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	$T		= $Ts[pane]
          			;
          			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
          
          			var 
          				dir			= c[pane].dir
          			,	_state		= (s.isClosed ? "_closed" : "_open")
          			,	spacing		= o["spacing"+ _state]
          			,	togAlign	= o["togglerAlign"+ _state]
          			,	togLen		= o["togglerLength"+ _state]
          			,	paneLen
          			,	offset
          			,	CSS = {}
          			;
          			if (spacing == 0) {
          				$R.hide();
          				return;
          			}
          			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
          				$R.show(); // in case was previously hidden
          
          			// Resizer Bar is ALWAYS same width/height of pane it is attached to
          			if (dir == "horz") { // north/south
          				paneLen = $P.outerWidth();
          				$R.css({
          					width:	max(1, cssW($R, paneLen)) // account for borders & padding
          				,	height:	max(1, cssH($R, spacing)) // ditto
          				,	left:	cssNum($P, "left")
          				});
          			}
          			else { // east/west
          				paneLen = $P.outerHeight();
          				$R.css({
          					height:	max(1, cssH($R, paneLen)) // account for borders & padding
          				,	width:	max(1, cssW($R, spacing)) // ditto
          				,	top:	cDims.top + getPaneSize("north", true)
          				//,	top:	cssNum($Ps["center"], "top")
          				});
          				
          			}
          
          			if ($T) {
          				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
          					$T.hide(); // always HIDE the toggler when 'sliding'
          					return;
          				}
          				else
          					$T.show(); // in case was previously hidden
          
          				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
          					togLen = paneLen;
          					offset = 0;
          				}
          				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
          					if (typeof togAlign == "string") {
          						switch (togAlign) {
          							case "top":
          							case "left":	offset = 0;
          											break;
          							case "bottom":
          							case "right":	offset = paneLen - togLen;
          											break;
          							case "middle":
          							case "center":
          							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
          						}
          					}
          					else { // togAlign = number
          						var x = parseInt(togAlign); //
          						if (togAlign >= 0) offset = x;
          						else offset = paneLen - togLen + x; // NOTE: x is negative!
          					}
          				}
          
          				var
          					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
          				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
          				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
          				;
          				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
          				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
          
          				if (dir == "horz") { // north/south
          					var width = cssW($T, togLen);
          					$T.css({
          						width:	max(0, width)  // account for borders & padding
          					,	height:	max(1, cssH($T, spacing)) // ditto
          					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
          				}
          				else { // east/west
          					var height = cssH($T, togLen);
          					$T.css({
          						height:	max(0, height)  // account for borders & padding
          					,	width:	max(1, cssW($T, spacing)) // ditto
          					,	top:	offset // POSITION the toggler
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
          				}
          
          
          			}
          
          			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
          			if (onInit && o.initHidden) {
          				$R.hide();
          				if ($T) $T.hide();
          			}
          		});
          	};
          
          
          	/**
          	 * resizeAll
          	 *
          	 * @callers  window.onresize(), callbacks or custom code
          	 */
          	var resizeAll = function () {
          		var
          			oldW	= cDims.innerWidth
          		,	oldH	= cDims.innerHeight
          		;
          		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
          
          		var
          			checkH	= (cDims.innerHeight < oldH)
          		,	checkW	= (cDims.innerWidth < oldW)
          		,	s, dir
          		;
          
          		if (checkH || checkW)
          			// NOTE special order for sizing: S-N-E-W
          			$.each(["south","north","east","west"], function(i,pane) {
          				s = state[pane];
          				dir = c[pane].dir;
          				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
          					setPaneMinMaxSizes(pane); // update pane-state
          					// shrink pane if 'too big' to fit
          					if (s.size > s.maxSize)
          						sizePane(pane, s.maxSize);
          				}
          			});
          
          		sizeMidPanes("all");
          		sizeHandles("all"); // reposition the toggler elements
          	};
          
          
          	/**
          	 * keyDown
          	 *
          	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
          	 *
          	 * @callers  document.keydown()
          	 */
          	function keyDown (evt) {
          		if (!evt) return true;
          		var code = evt.keyCode;
          		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
          
          		var
          			PANE = {
          				38: "north" // Up Cursor
          			,	40: "south" // Down Cursor
          			,	37: "west"  // Left Cursor
          			,	39: "east"  // Right Cursor
          			}
          		,	isCursorKey = (code >= 37 && code <= 40)
          		,	ALT = evt.altKey // no worky!
          		,	SHIFT = evt.shiftKey
          		,	CTRL = evt.ctrlKey
          		,	pane = false
          		,	s, o, k, m, el
          		;
          
          		if (!CTRL && !SHIFT)
          			return true; // no modifier key - abort
          		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
          			pane = PANE[code];
          		else // check to see if this matches a custom-hotkey
          			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
          				o = options[p];
          				k = o.customHotkey;
          				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
          				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
          					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
          						pane = p;
          						return false; // BREAK
          					}
          				}
          			});
          
          		if (!pane) return true; // no hotkey - abort
          
          		// validate pane
          		o = options[pane]; // get pane options
          		s = state[pane]; // get pane options
          		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
          
          		// see if user is in a 'form field' because may be 'selecting text'!
          		el = evt.target || evt.srcElement;
          		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
          			return true; // allow text-selection
          
          		// SYNTAX NOTES
          		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
          		// use "return false" to abort keystroke AND abort function
          		toggle(pane);
          		evt.stopPropagation();
          		evt.returnValue = false; // CANCEL key
          		return false;
          	};
          
          
          /*
           * ###########################
           *     UTILITY METHODS
           *   called externally only
           * ###########################
           */
          
          	function allowOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).attr("pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		;
          
          		// if pane is already raised, then reset it before doing it again!
          		// this would happen if allowOverflow is attached to BOTH the pane and an element 
          		if (s.cssSaved)
          			resetOverflow(pane); // reset previous CSS before continuing
          
          		// if pane is raised by sliding or resizing, or it's closed, then abort
          		if (s.isSliding || s.isResizing || s.isClosed) {
          			s.cssSaved = false;
          			return;
          		}
          
          		var
          			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
          		,	curCSS	= {}
          		,	of		= $P.css("overflow")
          		,	ofX		= $P.css("overflowX")
          		,	ofY		= $P.css("overflowY")
          		;
          		// determine which, if any, overflow settings need to be changed
          		if (of != "visible") {
          			curCSS.overflow = of;
          			newCSS.overflow = "visible";
          		}
          		if (ofX && ofX != "visible" && ofX != "auto") {
          			curCSS.overflowX = ofX;
          			newCSS.overflowX = "visible";
          		}
          		if (ofY && ofY != "visible" && ofY != "auto") {
          			curCSS.overflowY = ofX;
          			newCSS.overflowY = "visible";
          		}
          
          		// save the current overflow settings - even if blank!
          		s.cssSaved = curCSS;
          
          		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
          		$P.css( newCSS );
          
          		// make sure the zIndex of all other panes is normal
          		$.each(c.allPanes.split(","), function(i, p) {
          			if (p != pane) resetOverflow(p);
          		});
          
          	};
          
          	function resetOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		,	CSS		= s.cssSaved || {}
          		;
          		// reset the zIndex
          		if (!s.isSliding && !s.isResizing)
          			$P.css("zIndex", c.zIndex.pane_normal);
          
          		// reset Overflow - if necessary
          		$P.css( CSS );
          
          		// clear var
          		s.cssSaved = false;
          	};
          
          
          	/**
          	* getBtn
          	*
          	* Helper function to validate params received by addButton utilities
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
          	*/
          	function getBtn(selector, pane, action) {
          		var
          			$E = $(selector)
          		,	err = "Error Adding Button \n\nInvalid "
          		;
          		if (!$E.length) // element not found
          			alert(err+"selector: "+ selector);
          		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
          			alert(err+"pane: "+ pane);
          		else { // VALID
          			var btn = options[pane].buttonClass +"-"+ action;
          			$E.addClass( btn +" "+ btn +"-"+ pane );
          			return $E;
          		}
          		return false;  // INVALID
          	};
          
          
          	/**
          	* addToggleBtn
          	*
          	* Add a custom Toggler button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addToggleBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "toggle");
          		if ($E)
          			$E
          				.attr("title", state[pane].isClosed ? "Open" : "Close")
          				.click(function (evt) {
          					toggle(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addOpenBtn
          	*
          	* Add a custom Open button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addOpenBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "open");
          		if ($E)
          			$E
          				.attr("title", "Open")
          				.click(function (evt) {
          					open(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addCloseBtn
          	*
          	* Add a custom Close button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addCloseBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "close");
          		if ($E)
          			$E
          				.attr("title", "Close")
          				.click(function (evt) {
          					close(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addPinBtn
          	*
          	* Add a custom Pin button for a pane
          	*
          	* Four classes are added to the element, based on the paneClass for the associated pane...
          	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
          	*  - ui-layout-pane-pin
          	*  - ui-layout-pane-west-pin
          	*  - ui-layout-pane-pin-up
          	*  - ui-layout-pane-west-pin-up
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
          	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
          	*/
          	function addPinBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "pin");
          		if ($E) {
          			var s = state[pane];
          			$E.click(function (evt) {
          				setPinState($(this), pane, (s.isSliding || s.isClosed));
          				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
          				else close( pane ); // slide-closed
          				evt.stopPropagation();
          			});
          			// add up/down pin attributes and classes
          			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
          			// add this pin to the pane data so we can 'sync it' automatically
          			// PANE.pins key is an array so we can store multiple pins for each pane
          			c[pane].pins.push( selector ); // just save the selector string
          		}
          	};
          
          	/**
          	* syncPinBtns
          	*
          	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
          	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
          	*
          	* @callers  open(), close()
          	* @params  pane   These are the params returned to callbacks by layout()
          	* @params  doPin  True means set the pin 'down', False means 'up'
          	*/
          	function syncPinBtns (pane, doPin) {
          		$.each(c[pane].pins, function (i, selector) {
          			setPinState($(selector), pane, doPin);
          		});
          	};
          
          	/**
          	* setPinState
          	*
          	* Change the class of the pin button to make it look 'up' or 'down'
          	*
          	* @callers  addPinBtn(), syncPinBtns()
          	* @param Element  $Pin		The pin-span element in a jQuery wrapper
          	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
          	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
          	*/
          	function setPinState ($Pin, pane, doPin) {
          		var updown = $Pin.attr("pin");
          		if (updown && doPin == (updown=="down")) return; // already in correct state
          		var
          			root	= options[pane].buttonClass
          		,	class1	= root +"-pin"
          		,	class2	= class1 +"-"+ pane
          		,	UP1		= class1 + "-up"
          		,	UP2		= class2 + "-up"
          		,	DN1		= class1 + "-down"
          		,	DN2		= class2 + "-down"
          		;
          		$Pin
          			.attr("pin", doPin ? "down" : "up") // logic
          			.attr("title", doPin ? "Un-Pin" : "Pin")
          			.removeClass( doPin ? UP1 : DN1 ) 
          			.removeClass( doPin ? UP2 : DN2 ) 
          			.addClass( doPin ? DN1 : UP1 ) 
          			.addClass( doPin ? DN2 : UP2 ) 
          		;
          	};
          
          
          /*
           * ###########################
           * CREATE/RETURN BORDER-LAYOUT
           * ###########################
           */
          
          	// init global vars
          	var 
          		$Container = $(this).css({ overflow: "hidden" }) // Container elem
          	,	$Ps		= {} // Panes x4	- set in initPanes()
          	,	$Cs		= {} // Content x4	- set in initPanes()
          	,	$Rs		= {} // Resizers x4	- set in initHandles()
          	,	$Ts		= {} // Togglers x4	- set in initHandles()
          	//	object aliases
          	,	c		= config // alias for config hash
          	,	cDims	= state.container // alias for easy access to 'container dimensions'
          	;
          
          	// create the border layout NOW
          	create();
          
          	// return object pointers to expose data & option Properties, and primary action Methods
          	return {
          		options:		options			// property - options hash
          	,	state:			state			// property - dimensions hash
          	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
          	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
          	,	open:			open			// method - ditto
          	,	close:			close			// method - ditto
          	,	hide:			hide			// method - ditto
          	,	show:			show			// method - ditto
          	,	resizeContent:	sizeContent		// method - ditto
          	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
          	,	resizeAll:		resizeAll		// method - no parameters
          	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
          	,	addOpenBtn:		addOpenBtn		// utility - ditto
          	,	addCloseBtn:	addCloseBtn		// utility - ditto
          	,	addPinBtn:		addPinBtn		// utility - ditto
          	,	allowOverflow:	allowOverflow	// utility - pass calling element
          	,	resetOverflow:	resetOverflow	// utility - ditto
          	,	cssWidth:		cssW
          	,	cssHeight:		cssH
          	};
          
          }
          })( jQuery );
          Evidence
          TODO
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        34. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSER\b and was detected 6 times, the first in the element starting with: " * @params JSON d Data/options passed by user - may be a single level or nested levels ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (379 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 82920
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"82920-1230357900000"
          Last-Modified: Sat, 27 Dec 2008 06:05:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (82920 bytes)
          /*
           * jquery.layout 1.2.0
           *
           * Copyright (c) 2008 
           *   Fabrizio Balliano (http://www.fabrizioballiano.net)
           *   Kevin Dalman (http://allpro.net)
           *
           * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
           * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
           *
           * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
           * $Rev: 203 $
           * 
           * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
           */
          (function($) {
          
          $.fn.layout = function (opts) {
          
          /*
           * ###########################
           *   WIDGET CONFIG & OPTIONS
           * ###########################
           */
          
          	// DEFAULTS for options
          	var 
          		prefix = "ui-layout-" // prefix for ALL selectors and classNames
          	,	defaults = { //	misc default values
          			paneClass:				prefix+"pane"		// ui-layout-pane
          		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
          		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
          		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
          		,	buttonClass:			prefix+"button"		// ui-layout-button
          		,	contentSelector:		"."+prefix+"content"// ui-layout-content
          		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
          		}
          	;
          
          	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
          	var options = {
          		name:						""			// FUTURE REFERENCE - not used right now
          	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
          	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
          			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
          		,	closable:				true		// pane can open & close
          		,	resizable:				true		// when open, pane can be resized 
          		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
          		//,	paneSelector:			[ ]			// MUST be pane-specific!
          		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
          		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
          		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
          		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
          		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
          		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
          		,	resizerDragOpacity:		1			// option for ui.draggable
          		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
          		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
          		//,	size:					100			// inital size of pane - defaults are set 'per pane'
          		,	minSize:				0			// when manually resizing a pane
          		,	maxSize:				0			// ditto, 0 = no limit
          		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
          		,	spacing_closed:			6			// ditto - when pane is 'closed'
          		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
          		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
          		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
          		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
          		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
          		,	togglerTip_closed:		"Open"		// ditto
          		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
          		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
          		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
          		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
          		,	slideTrigger_close:		"mouseout"	// click, mouseout
          		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
          		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
          		,	togglerContent_closed:	""			// ditto
          		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
          		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
          		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
          		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
          		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
          		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
          		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
          		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
          		,	initClosed:				false		// true = init pane as 'closed'
          		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
          		
          		/*	callback options do not have to be set - listed here for reference only
          		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
          		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
          		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
          		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
          		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
          		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
          		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
          		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
          		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
          		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
          		*/
          		}
          	,	north: {
          			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
          		,	size:					"auto"
          		,	resizerCursor:			"n-resize"
          		}
          	,	south: {
          			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
          		,	size:					"auto"
          		,	resizerCursor:			"s-resize"
          		}
          	,	east: {
          			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
          		,	size:					200
          		,	resizerCursor:			"e-resize"
          		}
          	,	west: {
          			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
          		,	size:					200
          		,	resizerCursor:			"w-resize"
          		}
          	,	center: {
          			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
          		}
          
          	};
          
          
          	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
          		slide:	{
          			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	drop:	{
          			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	scale:	{
          			all:	{ duration:  "fast"	}
          		}
          	};
          
          
          	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
          	var config = {
          		allPanes:		"north,south,east,west,center"
          	,	borderPanes:	"north,south,east,west"
          	,	zIndex: { // set z-index values here
          			resizer_normal:	1		// normal z-index for resizer-bars
          		,	pane_normal:	2		// normal z-index for panes
          		,	mask:			4		// overlay div used to mask pane(s) during resizing
          		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
          		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
          		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
          		}
          	,	resizers: {
          			cssReq: {
          				position: 	"absolute"
          			,	padding: 	0
          			,	margin: 	0
          			,	fontSize:	"1px"
          			,	textAlign:	"left" // to counter-act "center" alignment!
          			,	overflow: 	"hidden" // keep toggler button from overflowing
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#DDD"
          			,	border:		"none"
          			}
          		}
          	,	togglers: {
          			cssReq: {
          				position: 	"absolute"
          			,	display: 	"block"
          			,	padding: 	0
          			,	margin: 	0
          			,	overflow:	"hidden"
          			,	textAlign:	"center"
          			,	fontSize:	"1px"
          			,	cursor: 	"pointer"
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#AAA"
          			}
          		}
          	,	content: {
          			cssReq: {
          				overflow:	"auto"
          			}
          		,	cssDef: {}
          		}
          	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
          			cssReq: {
          				position: 	"absolute"
          			,	margin:		0
          			,	zIndex: 	2
          			}
          		,	cssDef: {
          				padding:	"10px"
          			,	background:	"#FFF"
          			,	border:		"1px solid #BBB"
          			,	overflow:	"auto"
          			}
          		}
          	,	north: {
          			edge:			"top"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		0
          			,	bottom: 	"auto"
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	south: {
          			edge:			"bottom"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		"auto"
          			,	bottom: 	0
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	east: {
          			edge:			"right"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		"auto"
          			,	right: 		0
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	west: {
          			edge:			"left"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		0
          			,	right: 		"auto"
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	center: {
          			dir:			"center"
          		,	cssReq: {
          				left: 		"auto" // DYNAMIC
          			,	right: 		"auto" // DYNAMIC
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			,	width: 		"auto"
          			}
          		}
          	};
          
          
          	// DYNAMIC DATA
          	var state = {
          		// generate random 'ID#' to identify layout - used to create global namespace for timers
          		id:			Math.floor(Math.random() * 10000)
          	,	container:	{}
          	,	north:		{}
          	,	south:		{}
          	,	east:		{}
          	,	west:		{}
          	,	center:		{}
          	};
          
          
          	var 
          		altEdge = {
          			top:	"bottom"
          		,	bottom: "top"
          		,	left:	"right"
          		,	right:	"left"
          		}
          	,	altSide = {
          			north:	"south"
          		,	south:	"north"
          		,	east: 	"west"
          		,	west: 	"east"
          		}
          	;
          
          
          /*
           * ###########################
           *  INTERNAL HELPER FUNCTIONS
           * ###########################
           */
          
          	/**
          	 * isStr
          	 *
          	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
          	 */
          	var isStr = function (o) {
          		if (typeof o == "string")
          			return true;
          		else if (typeof o == "object") {
          			try {
          				var match = o.constructor.toString().match(/string/i); 
          				return (match !== null);
          			} catch (e) {} 
          		}
          		return false;
          	};
          
          	/**
          	 * str
          	 *
          	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
          	 *  else returns the original object
          	 */
          	var str = function (o) {
          		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
          		else return o;
          	};
          
          	/**
          	 * min / max
          	 *
          	 * Alias for Math.min/.max to simplify coding
          	 */
          	var min = function (x,y) { return Math.min(x,y); };
          	var max = function (x,y) { return Math.max(x,y); };
          
          	/**
          	 * transformData
          	 *
          	 * Processes the options passed in and transforms them into the format used by layout()
          	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
          	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
          	 * To update effects, options MUST use nested-keys format, with an effects key
          	 *
          	 * @callers  initOptions()
          	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
          	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
          	 */
          	var transformData = function (d) {
          		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
          		d = d || {};
          		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
          			json = $.extend( json, d ); // already in json format - add to base keys
          		else
          			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
          			$.each( d, function (key,val) {
          				a = key.split("__");
          				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
          			});
          		return json;
          	};
          
          	/**
          	 * setFlowCallback
          	 *
          	 * Set an INTERNAL callback to avoid simultaneous animation
          	 * Runs only if needed and only if all callbacks are not 'already set'!
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var setFlowCallback = function (action, pane, param) {
          		var
          			cb = action +","+ pane +","+ (param ? 1 : 0)
          		,	cP, cbPane
          		;
          		$.each(c.borderPanes.split(","), function (i,p) {
          			if (c[p].isMoving) {
          				bindCallback(p); // TRY to bind a callback
          				return false; // BREAK
          			}
          		});
          
          		function bindCallback (p, test) {
          			cP = c[p];
          			if (!cP.doCallback) {
          				cP.doCallback = true;
          				cP.callback = cb;
          			}
          			else { // try to 'chain' this callback
          				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
          				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
          					bindCallback (cpPane, true); // RECURSE
          			}
          		}
          	};
          
          	/**
          	 * execFlowCallback
          	 *
          	 * RUN the INTERNAL callback for this pane - if one exists
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var execFlowCallback = function (pane) {
          		var cP = c[pane];
          
          		// RESET flow-control flaGs
          		c.isLayoutBusy = false;
          		delete cP.isMoving;
          		if (!cP.doCallback || !cP.callback) return;
          
          		cP.doCallback = false; // RESET logic flag
          
          		// EXECUTE the callback
          		var
          			cb = cP.callback.split(",")
          		,	param = (cb[2] > 0 ? true : false)
          		;
          		if (cb[0] == "open")
          			open( cb[1], param  );
          		else if (cb[0] == "close")
          			close( cb[1], param );
          
          		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
          	};
          
          	/**
          	 * execUserCallback
          	 *
          	 * Executes a Callback function after a trigger event, like resize, open or close
          	 *
          	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
          	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
          	 */
          	var execUserCallback = function (pane, v_fn) {
          		if (!v_fn) return;
          		var fn;
          		try {
          			if (typeof v_fn == "function")
          				fn = v_fn;	
          			else if (typeof v_fn != "string")
          				return;
          			else if (v_fn.indexOf(",") > 0) {
          				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
          				var
          					args = v_fn.split(",")
          				,	fn = eval(args[0])
          				;
          				if (typeof fn=="function" && args.length > 1)
          					return fn(args[1]); // pass the argument parsed from 'list'
          			}
          			else // just the name of an external function?
          				fn = eval(v_fn);
          
          			if (typeof fn=="function")
          				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
          				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
          		}
          		catch (ex) {}
          	};
          
          	/**
          	 * cssNum
          	 *
          	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
          	 *
          	 * @callers  Called by many methods
          	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
          	 * @param String  property  The name of the CSS property, eg: top, width, etc.
          	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
          	 */
          	var cssNum = function ($E, prop) {
          		var
          			val = 0
          		,	hidden = false
          		,	visibility = ""
          		;
          		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
          			if ($.curCSS($E[0], "display", true) == "none") {
          				hidden = true;
          				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
          				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
          			}
          		}
          
          		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
          
          		if (hidden) { // WAS hidden, so put back the way it was
          			$E.css({ display: "none" });
          			if (visibility && visibility != "hidden")
          				$E.css({ visibility: visibility }); // reset 'visibility'
          		}
          
          		return val;
          	};
          
          	/**
          	 * cssW / cssH / cssSize
          	 *
          	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
          	 *
          	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
          	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
          	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
          	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
          	 *
          	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
          	 */
          	var cssW = function (e, outerWidth) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerWidth <= 0)
          			return 0;
          		else if (!(outerWidth>0))
          			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
          
          		if (!$.boxModel)
          			return outerWidth;
          
          		else // strip border and padding size from outerWidth to get CSS Width
          			return outerWidth
          				- cssNum($E, "paddingLeft")		
          				- cssNum($E, "paddingRight")
          				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
          				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
          			;
          	};
          	var cssH = function (e, outerHeight) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerHeight <= 0)
          			return 0;
          		else if (!(outerHeight>0))
          			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
          
          		if (!$.boxModel)
          			return outerHeight;
          
          		else // strip border and padding size from outerHeight to get CSS Height
          			return outerHeight
          				- cssNum($E, "paddingTop")
          				- cssNum($E, "paddingBottom")
          				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
          				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
          			;
          	};
          	var cssSize = function (pane, outerSize) {
          		if (c[pane].dir=="horz") // pane = north or south
          			return cssH(pane, outerSize);
          		else // pane = east or west
          			return cssW(pane, outerSize);
          	};
          
          	/**
          	 * getPaneSize
          	 *
          	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
          	 *
          	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
          	 */
          	var getPaneSize = function (pane, inclSpace) {
          		var 
          			$P	= $Ps[pane]
          		,	o	= options[pane]
          		,	s	= state[pane]
          		,	oSp	= (inclSpace ? o.spacing_open : 0)
          		,	cSp	= (inclSpace ? o.spacing_closed : 0)
          		;
          		if (!$P || s.isHidden)
          			return 0;
          		else if (s.isClosed || (s.isSliding && inclSpace))
          			return cSp;
          		else if (c[pane].dir == "horz")
          			return $P.outerHeight() + oSp;
          		else // dir == "vert"
          			return $P.outerWidth() + oSp;
          	};
          
          	var setPaneMinMaxSizes = function (pane) {
          		var 
          			d				= cDims
          		,	edge			= c[pane].edge
          		,	dir				= c[pane].dir
          		,	o				= options[pane]
          		,	s				= state[pane]
          		,	$P				= $Ps[pane]
          		,	$altPane		= $Ps[ altSide[pane] ]
          		,	paneSpacing		= o.spacing_open
          		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
          		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
          		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
          		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
          		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
          		,	minSize			= s.minSize || 0
          		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
          		,	minPos, maxPos	// used to set resizing limits
          		;
          		switch (pane) {
          			case "north":	minPos = d.offsetTop + minSize;
          							maxPos = d.offsetTop + maxSize;
          							break;
          			case "west":	minPos = d.offsetLeft + minSize;
          							maxPos = d.offsetLeft + maxSize;
          							break;
          			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
          							maxPos = d.offsetTop + d.innerHeight - minSize;
          							break;
          			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
          							maxPos = d.offsetLeft + d.innerWidth - minSize;
          							break;
          		}
          		// save data to pane-state
          		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
          	};
          
          	/**
          	 * getPaneDims
          	 *
          	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
          	 *
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
          	 */
          	var getPaneDims = function () {
          		var d = {
          			top:	getPaneSize("north", true) // true = include 'spacing' value for p
          		,	bottom:	getPaneSize("south", true)
          		,	left:	getPaneSize("west", true)
          		,	right:	getPaneSize("east", true)
          		,	width:	0
          		,	height:	0
          		};
          
          		with (d) {
          			width 	= cDims.innerWidth - left - right;
          			height 	= cDims.innerHeight - bottom - top;
          			// now add the 'container border/padding' to get final positions - relative to the container
          			top		+= cDims.top;
          			bottom	+= cDims.bottom;
          			left	+= cDims.left;
          			right	+= cDims.right;
          		}
          
          		return d;
          	};
          
          
          	/**
          	 * getElemDims
          	 *
          	 * Returns data for setting size of an element (container or a pane).
          	 *
          	 * @callers  create(), onWindowResize() for container, plus others for pane
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
          	 */
          	var getElemDims = function ($E) {
          		var
          			d = {} // dimensions hash
          		,	e, b, p // edge, border, padding
          		;
          
          		$.each("Left,Right,Top,Bottom".split(","), function () {
          			e = str(this);
          			b = d["border" +e] = cssNum($E, "border"+e+"Width");
          			p = d["padding"+e] = cssNum($E, "padding"+e);
          			d["offset" +e] = b + p; // total offset of content from outer edge
          			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
          			if ($E == $Container)
          				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
          		});
          
          		d.innerWidth  = d.outerWidth  = $E.outerWidth();
          		d.innerHeight = d.outerHeight = $E.outerHeight();
          		if ($.boxModel) {
          			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
          			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
          		}
          
          		return d;
          	};
          
          
          	var setTimer = function (pane, action, fn, ms) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) return; // timer already set!
          		else Timers[name] = setTimeout(fn, ms);
          	};
          
          	var clearTimer = function (pane, action) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) {
          			clearTimeout( Timers[name] );
          			delete Timers[name];
          			return true;
          		}
          		else
          			return false;
          	};
          
          
          /*
           * ###########################
           *   INITIALIZATION METHODS
           * ###########################
           */
          
          	/**
          	 * create
          	 *
          	 * Initialize the layout - called automatically whenever an instance of layout is created
          	 *
          	 * @callers  NEVER explicity called
          	 * @returns  An object pointer to the instance created
          	 */
          	var create = function () {
          		// initialize config/options
          		initOptions();
          
          		// initialize all objects
          		initContainer();	// set CSS as needed and init state.container dimensions
          		initPanes();		// size & position all panes
          		initHandles();		// create and position all resize bars & togglers buttons
          		initResizable();	// activate resizing on all panes where resizable=true
          		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
          
          		if (options.scrollToBookmarkOnLoad)
          			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
          
          		// bind hotkey function - keyDown - if required
          		initHotkeys();
          
          		// bind resizeAll() for 'this layout instance' to window.resize event
          		$(window).resize(function () {
          			var timerID = "timerLayout_"+state.id;
          			if (window[timerID]) clearTimeout(window[timerID]);
          			window[timerID] = null;
          			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
          				window[timerID] = setTimeout(resizeAll, 100);
          			else // most other browsers have a built-in delay before firing the resize event
          				resizeAll(); // resize all layout elements NOW!
          		});
          	};
          
          	/**
          	 * initContainer
          	 *
          	 * Validate and initialize container CSS and events
          	 *
          	 * @callers  create()
          	 */
          	var initContainer = function () {
          		try { // format html/body if this is a full page layout
          			if ($Container[0].tagName == "BODY") {
          				$("html").css({
          					height:		"100%"
          				,	overflow:	"hidden"
          				});
          				$("body").css({
          					position:	"relative"
          				,	height:		"100%"
          				,	overflow:	"hidden"
          				,	margin:		0
          				,	padding:	0		// TODO: test whether body-padding could be handled?
          				,	border:		"none"	// a body-border creates problems because it cannot be measured!
          				});
          			}
          			else { // set required CSS - overflow and position
          				var
          					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
          				,	p	= $Container.css("position")
          				,	h	= $Container.css("height")
          				;
          				// if this is a NESTED layout, then outer-pane ALREADY has position and height
          				if (!$Container.hasClass("ui-layout-pane")) {
          					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
          						CSS.position = "relative"; // container MUST have a 'position'
          					if (!h || h=="auto")
          						CSS.height = "100%"; // container MUST have a 'height'
          				}
          				$Container.css( CSS );
          			}
          		} catch (ex) {}
          
          		// get layout-container dimensions (updated when necessary)
          		cDims = state.container = getElemDims( $Container ); // update data-pointer too
          	};
          
          	/**
          	 * initHotkeys
          	 *
          	 * Bind layout hotkeys - if options enabled
          	 *
          	 * @callers  create()
          	 */
          	var initHotkeys = function () {
          		// bind keyDown to capture hotkeys, if option enabled for ANY pane
          		$.each(c.borderPanes.split(","), function (i,pane) {
          			var o = options[pane];
          			if (o.enableCursorHotkey || o.customHotkey) {
          				$(document).keydown( keyDown ); // only need to bind this ONCE
          				return false; // BREAK - binding was done
          			}
          		});
          	};
          
          	/**
          	 * initOptions
          	 *
          	 * Build final CONFIG and OPTIONS data
          	 *
          	 * @callers  create()
          	 */
          	var initOptions = function () {
          		// simplify logic by making sure passed 'opts' var has basic keys
          		opts = transformData( opts );
          
          		// update default effects, if case user passed key
          		if (opts.effects) {
          			$.extend( effects, opts.effects );
          			delete opts.effects;
          		}
          
          		// see if any 'global options' were specified
          		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
          			if (opts[key] !== undefined)
          				options[key] = opts[key];
          			else if (opts.defaults[key] !== undefined) {
          				options[key] = opts.defaults[key];
          				delete opts.defaults[key];
          			}
          		});
          
          		// remove any 'defaults' that MUST be set 'per-pane'
          		$.each("paneSelector,resizerCursor,customHotkey".split(","),
          			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
          		);
          
          		// now update options.defaults
          		$.extend( options.defaults, opts.defaults );
          		// make sure required sub-keys exist
          		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
          
          		// merge all config & options for the 'center' pane
          		c.center = $.extend( true, {}, c.defaults, c.center );
          		$.extend( options.center, opts.center );
          		// Most 'default options' do not apply to 'center', so add only those that DO
          		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
          		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
          			function (idx,key) { options.center[key] = o_Center[key]; }
          		);
          
          		var defs = options.defaults;
          
          		// create a COMPLETE set of options for EACH border-pane
          		$.each(c.borderPanes.split(","), function(i,pane) {
          			// apply 'pane-defaults' to CONFIG.PANE
          			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
          			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
          			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
          
          			// make sure we have base-classes
          			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
          			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
          			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
          
          			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
          			$.each(["_open","_close",""], function (i,n) { 
          				var
          					sName		= "fxName"+n
          				,	sSpeed		= "fxSpeed"+n
          				,	sSettings	= "fxSettings"+n
          				;
          				// recalculate fxName according to specificity rules
          				o[sName] =
          					opts[pane][sName]		// opts.west.fxName_open
          				||	opts[pane].fxName		// opts.west.fxName
          				||	opts.defaults[sName]	// opts.defaults.fxName_open
          				||	opts.defaults.fxName	// opts.defaults.fxName
          				||	o[sName]				// options.west.fxName_open
          				||	o.fxName				// options.west.fxName
          				||	defs[sName]				// options.defaults.fxName_open
          				||	defs.fxName				// options.defaults.fxName
          				||	"none"
          				;
          				// validate fxName to be sure is a valid effect
          				var fxName = o[sName];
          				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
          					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
          				// set vars for effects subkeys to simplify logic
          				var
          					fx = effects[fxName]	|| {} // effects.slide
          				,	fx_all	= fx.all		|| {} // effects.slide.all
          				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
          				;
          				// RECREATE the fxSettings[_open|_close] keys using specificity rules
          				o[sSettings] = $.extend(
          					{}
          				,	fx_all						// effects.slide.all
          				,	fx_pane						// effects.slide.west
          				,	defs.fxSettings || {}		// options.defaults.fxSettings
          				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
          				,	o.fxSettings				// options.west.fxSettings
          				,	o[sSettings]				// options.west.fxSettings_open
          				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
          				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
          				,	opts[pane].fxSettings		// opts.west.fxSettings
          				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
          				);
          				// recalculate fxSpeed according to specificity rules
          				o[sSpeed] =
          					opts[pane][sSpeed]		// opts.west.fxSpeed_open
          				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
          				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
          				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
          				||	o[sSpeed]				// options.west.fxSpeed_open
          				||	o[sSettings].duration	// options.west.fxSettings_open.duration
          				||	o.fxSpeed				// options.west.fxSpeed
          				||	o.fxSettings.duration	// options.west.fxSettings.duration
          				||	defs.fxSpeed			// options.defaults.fxSpeed
          				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
          				||	fx_pane.duration		// effects.slide.west.duration
          				||	fx_all.duration			// effects.slide.all.duration
          				||	"normal"				// DEFAULT
          				;
          				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
          			});
          		});
          	};
          
          	/**
          	 * initPanes
          	 *
          	 * Initialize module objects, styling, size and position for all panes
          	 *
          	 * @callers  create()
          	 */
          	var initPanes = function () {
          		// NOTE: do north & south FIRST so we can measure their height - do center LAST
          		$.each(c.allPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	fx		= s.fx
          			,	dir		= c[pane].dir
          			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
          			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
          			,	minSize	= o.minSize || 1
          			,	maxSize	= o.maxSize || 9999
          			,	spacing	= o.spacing_open || 0
          			,	sel		= o.paneSelector
          			,	isIE6	= ($.browser.msie && $.browser.version < 7)
          			,	CSS		= {}
          			,	$P, $C
          			;
          			$Cs[pane] = false; // init
          
          			if (sel.substr(0,1)==="#") // ID selector
          				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
          				$P = $Ps[pane] = $Container.find(sel+":first");
          			else { // class or other selector
          				$P = $Ps[pane] = $Container.children(sel+":first");
          				// look for the pane nested inside a 'form' element
          				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
          			}
          
          			if (!$P.length) {
          				$Ps[pane] = false; // logic
          				return true; // SKIP to next
          			}
          
          			// add basic classes & attributes
          			$P
          				.attr("pane", pane) // add pane-identifier
          				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
          			;
          
          			// init pane-logic vars, etc.
          			if (pane != "center") {
          				s.isClosed  = false; // true = pane is closed
          				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
          				s.isResizing= false; // true = pane is in process of being resized
          				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
          				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
          				// create special keys for internal use
          				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
          			}
          
          			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
          			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
          			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
          			CSS = {};	// reset var
          
          			// set css-position to account for container borders & padding
          			switch (pane) {
          				case "north": 	CSS.top 	= cDims.top;
          								CSS.left 	= cDims.left;
          								CSS.right	= cDims.right;
          								break;
          				case "south": 	CSS.bottom	= cDims.bottom;
          								CSS.left 	= cDims.left;
          								CSS.right 	= cDims.right;
          								break;
          				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
          								break;
          				case "east": 	CSS.right 	= cDims.right; // ditto
          								break;
          				case "center":	// top, left, width & height set by sizeMidPanes()
          			}
          
          			if (dir == "horz") { // north or south pane
          				if (size === 0 || size == "auto") {
          					$P.css({ height: "auto" });
          					size = $P.outerHeight();
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerHeight - spacing);
          				CSS.height = max(1, cssH(pane, size));
          				s.size = size; // update state
          				// make sure minSize is sufficient to avoid errors
          				s.maxSize = maxSize; // init value
          				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
          				// handle IE6
          				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
          				$P.css(CSS); // apply size & position
          			}
          			else if (dir == "vert") { // east or west pane
          				if (size === 0 || size == "auto") {
          					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
          					size = $P.outerWidth();
          					$P.css({ float: "none" }); // RESET
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerWidth - spacing);
          				CSS.width = max(1, cssW(pane, size));
          				s.size = size; // update state
          				s.maxSize = maxSize; // init value
          				// make sure minSize is sufficient to avoid errors
          				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
          				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
          				sizeMidPanes(pane, null, true); // true = onInit
          			}
          			else if (pane == "center") {
          				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
          				sizeMidPanes("center", null, true); // true = onInit
          			}
          
          			// close or hide the pane if specified in settings
          			if (o.initClosed && o.closable) {
          				$P.hide().addClass("closed");
          				s.isClosed = true;
          			}
          			else if (o.initHidden || o.initClosed) {
          				hide(pane, true); // will be completely invisible - no resizer or spacing
          				s.isHidden = true;
          			}
          			else
          				$P.addClass("open");
          
          			// check option for auto-handling of pop-ups & drop-downs
          			if (o.showOverflowOnHover)
          				$P.hover( allowOverflow, resetOverflow );
          
          			/*
          			 *	see if this pane has a 'content element' that we need to auto-size
          			 */
          			if (o.contentSelector) {
          				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
          				if (!$C.length) {
          					$Cs[pane] = false;
          					return true; // SKIP to next
          				}
          				$C.css( c.content.cssReq );
          				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
          				// NO PANE-SCROLLING when there is a content-div
          				$P.css({ overflow: "hidden" });
          			}
          		});
          	};
          
          	/**
          	 * initHandles
          	 *
          	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
          	 *
          	 * @callers  create()
          	 */
          	var initHandles = function () {
          		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	rClass	= o.resizerClass
          			,	tClass	= o.togglerClass
          			,	$P		= $Ps[pane]
          			;
          			$Rs[pane] = false; // INIT
          			$Ts[pane] = false;
          
          			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
          
          			var 
          				edge	= c[pane].edge
          			,	isOpen	= $P.is(":visible")
          			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
          			,	_pane	= "-"+ pane // used for classNames
          			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
          			,	$R, $T
          			;
          			// INIT RESIZER BAR
          			$R = $Rs[pane] = $("<span></span>");
          	
          			if (isOpen && o.resizable)
          				; // this is handled by initResizable
          			else if (!isOpen && o.slidable)
          				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
          	
          			$R
          				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
          				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
          				.attr("resizer", pane) // so we can read this from the resizer
          				.css(c.resizers.cssReq) // add base/required styles
          				// POSITION of resizer bar - allow for container border & padding
          				.css(edge, cDims[edge] + getPaneSize(pane))
          				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
          				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
          				.appendTo($Container) // append DIV to container
          			;
          			 // ADD VISUAL STYLES
          			if (o.applyDefaultStyles)
          				$R.css(c.resizers.cssDef);
          
          			if (o.closable) {
          				// INIT COLLAPSER BUTTON
          				$T = $Ts[pane] = $("<div></div>");
          				$T
          					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
          					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
          					.css(c.togglers.cssReq) // add base/required styles
          					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
          					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
          					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
          					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
          					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
          					.appendTo($R) // append SPAN to resizer DIV
          				;
          
          				// ADD INNER-SPANS TO TOGGLER
          				if (o.togglerContent_open) // ui-layout-open
          					$("<span>"+ o.togglerContent_open +"</span>")
          						.addClass("content content-open")
          						.css("display", s.isClosed ? "none" : "block")
          						.appendTo( $T )
          					;
          				if (o.togglerContent_closed) // ui-layout-closed
          					$("<span>"+ o.togglerContent_closed +"</span>")
          						.addClass("content content-closed")
          						.css("display", s.isClosed ? "block" : "none")
          						.appendTo( $T )
          					;
          
          				 // ADD BASIC VISUAL STYLES
          				if (o.applyDefaultStyles)
          					$T.css(c.togglers.cssDef);
          
          				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          			}
          
          		});
          
          		// SET ALL HANDLE SIZES & LENGTHS
          		sizeHandles("all", true); // true = onInit
          	};
          
          	/**
          	 * initResizable
          	 *
          	 * Add resize-bars to all panes that specify it in options
          	 *
          	 * @dependancies  $.fn.resizable - will abort if not found
          	 * @callers  create()
          	 */
          	var initResizable = function () {
          		var
          			draggingAvailable = (typeof $.fn.draggable == "function")
          		,	minPosition, maxPosition, edge // set in start()
          		;
          
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			;
          			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
          				o.resizable = false;
          				return true; // skip to next
          			}
          
          			var 
          				rClass				= o.resizerClass
          			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
          			,	dragClass			= rClass+"-drag"			// resizer-drag
          			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
          			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
          			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
          			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
          			,	draggingClassSet	= false 					// logic var
          			,	$P 					= $Ps[pane]
          			,	$R					= $Rs[pane]
          			;
          
          			if (!s.isClosed)
          				$R
          					.attr("title", o.resizerTip)
          					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
          				;
          
          			$R.draggable({
          				containment:	$Container[0] // limit resizing to layout container
          			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
          			,	delay:			200
          			,	distance:		1
          			//	basic format for helper - style it using class: .ui-draggable-dragging
          			,	helper:			"clone"
          			,	opacity:		o.resizerDragOpacity
          			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
          			,	zIndex:			c.zIndex.resizing
          
          			,	start: function (e, ui) {
          					// onresize_start callback - will CANCEL hide if returns false
          					// TODO: CONFIRM that dragging can be cancelled like this???
          					if (false === execUserCallback(pane, o.onresize_start)) return false;
          
          					s.isResizing = true; // prevent pane from closing while resizing
          					clearTimer(pane, "closeSlider"); // just in case already triggered
          
          					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
          					draggingClassSet = false; // reset logic var - see drag()
          
          					// SET RESIZING LIMITS - used in drag()
          					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
          					setPaneMinMaxSizes(pane); // update pane-state
          					s.minPosition -= resizerWidth;
          					s.maxPosition -= resizerWidth;
          					edge = (c[pane].dir=="horz" ? "top" : "left");
          
          					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
          					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
          						$('<div class="ui-layout-mask"/>')
          							.css({
          								background:	"#fff"
          							,	opacity:	"0.001"
          							,	zIndex:		9
          							,	position:	"absolute"
          							,	width:		this.offsetWidth+"px"
          							,	height:		this.offsetHeight+"px"
          							})
          							.css($(this).offset()) // top & left
          							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
          						;
          					});
          				}
          
          			,	drag: function (e, ui) {
          					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
          						$(".ui-draggable-dragging")
          							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
          							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
          						;
          						draggingClassSet = true;
          						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
          						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
          					}
          					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
          					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
          					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
          				}
          
          			,	stop: function (e, ui) {
          					var 
          						dragPos	= ui.position
          					,	resizerPos
          					,	newSize
          					;
          					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
          	
          					switch (pane) {
          						case "north":	resizerPos = dragPos.top; break;
          						case "west":	resizerPos = dragPos.left; break;
          						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
          						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
          					}
          					// remove container margin from resizer position to get the pane size
          					newSize = resizerPos - cDims[ c[pane].edge ];
          
          					sizePane(pane, newSize);
          
          					// UN-MASK PANES MASKED IN drag.start
          					$("div.ui-layout-mask").remove(); // Remove iframe masks	
          
          					s.isResizing = false;
          				}
          
          			});
          		});
          	};
          
          
          
          /*
           * ###########################
           *       ACTION METHODS
           * ###########################
           */
          
          	/**
          	 * hide / show
          	 *
          	 * Completely 'hides' a pane, including its spacing - as if it does not exist
          	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
          	 *
          	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
          	 */
          	var hide = function (pane, onInit) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onhide_start)) return;
          
          		s.isSliding = false; // just in case
          
          		// now hide the elements
          		if ($R) $R.hide(); // hide resizer-bar
          		if (onInit || s.isClosed) {
          			s.isClosed = true; // to trigger open-animation on show()
          			s.isHidden  = true;
          			$P.hide(); // no animation when loading page
          			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          			execUserCallback(pane, o.onhide_end || o.onhide);
          		}
          		else {
          			s.isHiding = true; // used by onclose
          			close(pane, false); // adjust all panes to fit
          			//s.isHidden  = true; - will be set by close - if not cancelled
          		}
          	};
          
          	var show = function (pane, openPane) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onshow_start)) return;
          
          		s.isSliding = false; // just in case
          		s.isShowing = true; // used by onopen/onclose
          		//s.isHidden  = false; - will be set by open/close - if not cancelled
          
          		// now show the elements
          		if ($R && o.spacing_open > 0) $R.show();
          		if (openPane === false)
          			close(pane, true); // true = force
          		else
          			open(pane); // adjust all panes to fit
          	};
          
          
          	/**
          	 * toggle
          	 *
          	 * Toggles a pane open/closed by calling either open or close
          	 *
          	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
          	 */
          	var toggle = function (pane) {
          		var s = state[pane];
          		if (s.isHidden)
          			show(pane); // will call 'open' after unhiding it
          		else if (s.isClosed)
          			open(pane);
          		else
          			close(pane);
          	};
          
          	/**
          	 * close
          	 *
          	 * Close the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being closed, ie: north, south, east, or west
          	 */
          	var close = function (pane, force, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_sliding= "-sliding"
          		,	_closed	= "-closed"
          		// 	transfer logic vars to temp vars
          		,	isShowing = s.isShowing
          		,	isHiding = s.isHiding
          		;
          		// now clear the logic vars
          		delete s.isShowing;
          		delete s.isHiding;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!force && s.isClosed && !isShowing) return; // already closed
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("close", pane, force); // set a callback for this action, if possible
          			return; // ABORT 
          		}
          
          		// onclose_start callback - will CANCEL hide if returns false
          		// SKIP if just 'showing' a hidden pane as 'closed'
          		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		s.isClosed = true;
          		// update isHidden BEFORE sizing panes
          		if (isHiding) s.isHidden = true;
          		else if (isShowing) s.isHidden = false;
          
          		// sync any 'pin buttons'
          		syncPinBtns(pane, false);
          
          		// resize panes adjacent to this one
          		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          
          		// if this pane has a resizer bar, move it now
          		if ($R) {
          			$R
          				.css(edge, cDims[edge]) // move the resizer bar
          				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
          				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
          				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
          			;
          			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
          			if (o.resizable)
          				$R
          					.draggable("disable")
          					.css("cursor", "default")
          					.attr("title","")
          				;
          			// if pane has a toggler button, adjust that too
          			if ($T) {
          				$T
          					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
          					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
          					.attr("title", o.togglerTip_closed) // may be blank
          				;
          			}
          			sizeHandles(); // resize 'length' and position togglers for adjacent panes
          		}
          
          		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
          		if (doFX) {
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
          				lockPaneForFX(pane, false); // undo
          				if (!s.isClosed) return; // pane was opened before animation finished!
          				close_2();
          			});
          		}
          		else {
          			$P.hide(); // just hide pane NOW
          			close_2();
          		}
          
          		// SUBROUTINE
          		function close_2 () {
          			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          
          			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
          			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
          			// onhide OR onshow callback
          			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
          			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          
          	/**
          	 * open
          	 *
          	 * Open the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being opened, ie: north, south, east, or west
          	 */
          	var open = function (pane, slide, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_closed	= "-closed"
          		,	_sliding= "-sliding"
          		// 	transfer logic var to temp var
          		,	isShowing = s.isShowing
          		;
          		// now clear the logic var
          		delete s.isShowing;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!s.isClosed && !s.isSliding) return; // already open
          
          		// pane can ALSO be unhidden by just calling show(), so handle this scenario
          		if (s.isHidden && !isShowing) {
          			show(pane, true);
          			return;
          		}
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
          			return; // ABORT
          		}
          
          		// onopen_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onopen_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		// 'PIN PANE' - stop sliding
          		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
          			bindStopSlidingEvents(pane, false); // will set isSliding=false
          
          		s.isClosed = false;
          		// update isHidden BEFORE sizing panes
          		if (isShowing) s.isHidden = false;
          
          		// Container size may have changed - shrink the pane if now 'too big'
          		setPaneMinMaxSizes(pane); // update pane-state
          		if (s.size > s.maxSize) // pane is too big! resize it before opening
          			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
          
          		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
          
          		if (doFX) { // ANIMATE
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
          				lockPaneForFX(pane, false); // undo
          				if (s.isClosed) return; // pane was closed before animation finished!
          				open_2(); // continue
          			});
          		}
          		else {// no animation
          			$P.show();	// just show pane and...
          			open_2();	// continue
          		}
          
          		// SUBROUTINE
          		function open_2 () {
          			// NOTE: if isSliding, then other panes are NOT 'resized'
          			if (!s.isSliding) // resize all panes adjacent to this one
          				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
          
          			// if this pane has a toggler, move it now
          			if ($R) {
          				$R
          					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
          					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
          					.addClass( rClass+_open +" "+ rClass+_pane+_open )
          					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
          				;
          				if (o.resizable)
          					$R
          						.draggable("enable")
          						.css("cursor", o.resizerCursor)
          						.attr("title", o.resizerTip)
          					;
          				else
          					$R.css("cursor", "default"); // n-resize, s-resize, etc
          				// if pane also has a toggler button, adjust that too
          				if ($T) {
          					$T
          						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
          						.addClass( tClass+_open +" "+ tClass+_pane+_open )
          						.attr("title", o.togglerTip_open) // may be blank
          					;
          				}
          				sizeHandles("all"); // resize resizer & toggler sizes for all panes
          			}
          
          			// resize content every time pane opens - to be sure
          			sizeContent(pane);
          
          			// sync any 'pin buttons'
          			syncPinBtns(pane, !s.isSliding);
          
          			// onopen callback
          			execUserCallback(pane, o.onopen_end || o.onopen);
          
          			// onshow callback
          			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          	
          
          	/**
          	 * lockPaneForFX
          	 *
          	 * Must set left/top on East/South panes so animation will work properly
          	 *
          	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
          	 * @param Boolean  doLock  true = set left/top, false = remove
          	 */
          	var lockPaneForFX = function (pane, doLock) {
          		var $P = $Ps[pane];
          		if (doLock) {
          			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
          			if (pane=="south")
          				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
          			else if (pane=="east")
          				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
          		}
          		else {
          			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
          			if (pane=="south")
          				$P.css({ top: "auto" });
          			else if (pane=="east")
          				$P.css({ left: "auto" });
          		}
          	};
          
          
          	/**
          	 * bindStartSlidingEvent
          	 *
          	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
          	 *
          	 * @callers  open(), close()
          	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
          	 * @param Boolean  enable  Enable or Disable sliding?
          	 */
          	var bindStartSlidingEvent = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	$R		= $Rs[pane]
          		,	trigger	= o.slideTrigger_open
          		;
          		if (!$R || !o.slidable) return;
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
          		$R
          			// add or remove trigger event
          			[enable ? "bind" : "unbind"](trigger, slideOpen)
          			// set the appropriate cursor & title/tip
          			.css("cursor", (enable ? o.sliderCursor: "default"))
          			.attr("title", (enable ? o.sliderTip : ""))
          		;
          	};
          
          	/**
          	 * bindStopSlidingEvents
          	 *
          	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
          	 * Also increases zIndex when pane is sliding open
          	 * See bindStartSlidingEvent for code to control 'slide open'
          	 *
          	 * @callers  slideOpen(), slideClosed()
          	 * @param String  pane  The pane to process, 'north', 'south', etc.
          	 * @param Boolean  isOpen  Is pane open or closed?
          	 */
          	var bindStopSlidingEvents = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	s		= state[pane]
          		,	trigger	= o.slideTrigger_close
          		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          
          		s.isSliding = enable; // logic
          		clearTimer(pane, "closeSlider"); // just in case
          
          		// raise z-index when sliding
          		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
          		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
          
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
          
          		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
          		if (enable) { // BIND trigger events
          			$P.bind(trigger, slideClosed );
          			$R.bind(trigger, slideClosed );
          			if (trigger = "mouseout") {
          				$P.bind("mouseover", cancelMouseOut );
          				$R.bind("mouseover", cancelMouseOut );
          			}
          		}
          		else { // UNBIND trigger events
          			// TODO: why does unbind of a 'single function' not work reliably?
          			//$P[action](trigger, slideClosed );
          			$P.unbind(trigger);
          			$R.unbind(trigger);
          			if (trigger = "mouseout") {
          				//$P[action]("mouseover", cancelMouseOut );
          				$P.unbind("mouseover");
          				$R.unbind("mouseover");
          				clearTimer(pane, "closeSlider");
          			}
          		}
          
          		// SUBROUTINE for mouseout timer clearing
          		function cancelMouseOut (evt) {
          			clearTimer(pane, "closeSlider");
          			evt.stopPropagation();
          		}
          	};
          
          	var slideOpen = function () {
          		var pane = $(this).attr("resizer"); // attr added by initHandles
          		if (state[pane].isClosed) { // skip if already open!
          			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
          			open(pane, true); // true = slide - ie, called from here!
          		}
          	};
          
          	var slideClosed = function () {
          		var
          			$E = $(this)
          		,	pane = $E.attr("pane") || $E.attr("resizer")
          		,	o = options[pane]
          		,	s = state[pane]
          		;
          		if (s.isClosed || s.isResizing)
          			return; // skip if already closed OR in process of resizing
          		else if (o.slideTrigger_close == "click")
          			close_NOW(); // close immediately onClick
          		else // trigger = mouseout - use a delay
          			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
          
          		// SUBROUTINE for timed close
          		function close_NOW () {
          			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
          			if (!s.isClosed) close(pane); // skip if already closed!
          		}
          	};
          
          
          	/**
          	 * sizePane
          	 *
          	 * @callers  initResizable.stop()
          	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
          	 * @param Integer  newSize  The new size for this pane - will be validated
          	 */
          	var sizePane = function (pane, size) {
          		// TODO: accept "auto" as size, and size-to-fit pane content
          		var 
          			edge	= c[pane].edge
          		,	dir		= c[pane].dir
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          		// calculate 'current' min/max sizes
          		setPaneMinMaxSizes(pane); // update pane-state
          		// compare/update calculated min/max to user-options
          		s.minSize = max(s.minSize, o.minSize);
          		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
          		// validate passed size
          		size = max(size, s.minSize);
          		size = min(size, s.maxSize);
          		s.size = size; // update state
          
          		// move the resizer bar and resize the pane
          		$R.css( edge, size + cDims[edge] );
          		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
          
          		// resize all the adjacent panes, and adjust their toggler buttons
          		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
          		sizeHandles();
          		sizeContent(pane);
          		execUserCallback(pane, o.onresize_end || o.onresize);
          	};
          
          	/**
          	 * sizeMidPanes
          	 *
          	 * @callers  create(), open(), close(), onWindowResize()
          	 */
          	var sizeMidPanes = function (panes, overrideDims, onInit) {
          		if (!panes || panes == "all") panes = "east,west,center";
          
          		var d = getPaneDims();
          		if (overrideDims) $.extend( d, overrideDims );
          
          		$.each(panes.split(","), function() {
          			if (!$Ps[this]) return; // NO PANE - skip
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	hasRoom	= true
          			,	CSS		= {}
          			;
          
          			if (pane == "center") {
          				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
          				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
          				CSS.width  = max(1, cssW(pane, CSS.width));
          				CSS.height = max(1, cssH(pane, CSS.height));
          				hasRoom = (CSS.width > 1 && CSS.height > 1);
          				/*
          				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
          				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
          				 */
          				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
          					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
          					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
          				}
          			}
          			else { // for east and west, set only the height
          				CSS.top = d.top;
          				CSS.bottom = d.bottom;
          				CSS.height = max(1, cssH(pane, d.height));
          				hasRoom = (CSS.height > 1);
          			}
          
          			if (hasRoom) {
          				$P.css(CSS);
          				if (s.noRoom) {
          					s.noRoom = false;
          					if (s.isHidden) return;
          					else show(pane, !s.isClosed);
          					/* OLD CODE - keep until sure line above works right!
          					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
          					if ($R) $R.show();
          					*/
          				}
          				if (!onInit) {
          					sizeContent(pane);
          					execUserCallback(pane, o.onresize_end || o.onresize);
          				}
          			}
          			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
          				s.noRoom = true; // update state
          				if (s.isHidden) return;
          				if (onInit) { // skip onhide callback and other logic onLoad
          					$P.hide();
          					if ($R) $R.hide();
          				}
          				else hide(pane);
          			}
          		});
          	};
          
          
          	var sizeContent = function (panes) {
          		if (!panes || panes == "all") panes = c.allPanes;
          
          		$.each(panes.split(","), function() {
          			if (!$Cs[this]) return; // NO CONTENT - skip
          			var 
          				pane	= str(this)
          			,	ignore	= options[pane].contentIgnoreSelector
          			,	$P		= $Ps[pane]
          			,	$C		= $Cs[pane]
          			,	e_C		= $C[0]		// DOM element
          			,	height	= cssH($P);	// init to pane.innerHeight
          			;
          			$P.children().each(function() {
          				if (this == e_C) return; // Content elem - skip
          				var $E = $(this);
          				if (!ignore || !$E.is(ignore))
          					height -= $E.outerHeight();
          			});
          			if (height > 0)
          				height = cssH($C, height);
          			if (height < 1)
          				$C.hide(); // no room for content!
          			else
          				$C.css({ height: height }).show();
          		});
          	};
          
          
          	/**
          	 * sizeHandles
          	 *
          	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
          	 *
          	 * @callers  initHandles(), open(), close(), resizeAll()
          	 */
          	var sizeHandles = function (panes, onInit) {
          		if (!panes || panes == "all") panes = c.borderPanes;
          
          		$.each(panes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	$T		= $Ts[pane]
          			;
          			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
          
          			var 
          				dir			= c[pane].dir
          			,	_state		= (s.isClosed ? "_closed" : "_open")
          			,	spacing		= o["spacing"+ _state]
          			,	togAlign	= o["togglerAlign"+ _state]
          			,	togLen		= o["togglerLength"+ _state]
          			,	paneLen
          			,	offset
          			,	CSS = {}
          			;
          			if (spacing == 0) {
          				$R.hide();
          				return;
          			}
          			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
          				$R.show(); // in case was previously hidden
          
          			// Resizer Bar is ALWAYS same width/height of pane it is attached to
          			if (dir == "horz") { // north/south
          				paneLen = $P.outerWidth();
          				$R.css({
          					width:	max(1, cssW($R, paneLen)) // account for borders & padding
          				,	height:	max(1, cssH($R, spacing)) // ditto
          				,	left:	cssNum($P, "left")
          				});
          			}
          			else { // east/west
          				paneLen = $P.outerHeight();
          				$R.css({
          					height:	max(1, cssH($R, paneLen)) // account for borders & padding
          				,	width:	max(1, cssW($R, spacing)) // ditto
          				,	top:	cDims.top + getPaneSize("north", true)
          				//,	top:	cssNum($Ps["center"], "top")
          				});
          				
          			}
          
          			if ($T) {
          				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
          					$T.hide(); // always HIDE the toggler when 'sliding'
          					return;
          				}
          				else
          					$T.show(); // in case was previously hidden
          
          				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
          					togLen = paneLen;
          					offset = 0;
          				}
          				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
          					if (typeof togAlign == "string") {
          						switch (togAlign) {
          							case "top":
          							case "left":	offset = 0;
          											break;
          							case "bottom":
          							case "right":	offset = paneLen - togLen;
          											break;
          							case "middle":
          							case "center":
          							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
          						}
          					}
          					else { // togAlign = number
          						var x = parseInt(togAlign); //
          						if (togAlign >= 0) offset = x;
          						else offset = paneLen - togLen + x; // NOTE: x is negative!
          					}
          				}
          
          				var
          					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
          				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
          				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
          				;
          				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
          				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
          
          				if (dir == "horz") { // north/south
          					var width = cssW($T, togLen);
          					$T.css({
          						width:	max(0, width)  // account for borders & padding
          					,	height:	max(1, cssH($T, spacing)) // ditto
          					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
          				}
          				else { // east/west
          					var height = cssH($T, togLen);
          					$T.css({
          						height:	max(0, height)  // account for borders & padding
          					,	width:	max(1, cssW($T, spacing)) // ditto
          					,	top:	offset // POSITION the toggler
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
          				}
          
          
          			}
          
          			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
          			if (onInit && o.initHidden) {
          				$R.hide();
          				if ($T) $T.hide();
          			}
          		});
          	};
          
          
          	/**
          	 * resizeAll
          	 *
          	 * @callers  window.onresize(), callbacks or custom code
          	 */
          	var resizeAll = function () {
          		var
          			oldW	= cDims.innerWidth
          		,	oldH	= cDims.innerHeight
          		;
          		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
          
          		var
          			checkH	= (cDims.innerHeight < oldH)
          		,	checkW	= (cDims.innerWidth < oldW)
          		,	s, dir
          		;
          
          		if (checkH || checkW)
          			// NOTE special order for sizing: S-N-E-W
          			$.each(["south","north","east","west"], function(i,pane) {
          				s = state[pane];
          				dir = c[pane].dir;
          				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
          					setPaneMinMaxSizes(pane); // update pane-state
          					// shrink pane if 'too big' to fit
          					if (s.size > s.maxSize)
          						sizePane(pane, s.maxSize);
          				}
          			});
          
          		sizeMidPanes("all");
          		sizeHandles("all"); // reposition the toggler elements
          	};
          
          
          	/**
          	 * keyDown
          	 *
          	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
          	 *
          	 * @callers  document.keydown()
          	 */
          	function keyDown (evt) {
          		if (!evt) return true;
          		var code = evt.keyCode;
          		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
          
          		var
          			PANE = {
          				38: "north" // Up Cursor
          			,	40: "south" // Down Cursor
          			,	37: "west"  // Left Cursor
          			,	39: "east"  // Right Cursor
          			}
          		,	isCursorKey = (code >= 37 && code <= 40)
          		,	ALT = evt.altKey // no worky!
          		,	SHIFT = evt.shiftKey
          		,	CTRL = evt.ctrlKey
          		,	pane = false
          		,	s, o, k, m, el
          		;
          
          		if (!CTRL && !SHIFT)
          			return true; // no modifier key - abort
          		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
          			pane = PANE[code];
          		else // check to see if this matches a custom-hotkey
          			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
          				o = options[p];
          				k = o.customHotkey;
          				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
          				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
          					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
          						pane = p;
          						return false; // BREAK
          					}
          				}
          			});
          
          		if (!pane) return true; // no hotkey - abort
          
          		// validate pane
          		o = options[pane]; // get pane options
          		s = state[pane]; // get pane options
          		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
          
          		// see if user is in a 'form field' because may be 'selecting text'!
          		el = evt.target || evt.srcElement;
          		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
          			return true; // allow text-selection
          
          		// SYNTAX NOTES
          		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
          		// use "return false" to abort keystroke AND abort function
          		toggle(pane);
          		evt.stopPropagation();
          		evt.returnValue = false; // CANCEL key
          		return false;
          	};
          
          
          /*
           * ###########################
           *     UTILITY METHODS
           *   called externally only
           * ###########################
           */
          
          	function allowOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).attr("pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		;
          
          		// if pane is already raised, then reset it before doing it again!
          		// this would happen if allowOverflow is attached to BOTH the pane and an element 
          		if (s.cssSaved)
          			resetOverflow(pane); // reset previous CSS before continuing
          
          		// if pane is raised by sliding or resizing, or it's closed, then abort
          		if (s.isSliding || s.isResizing || s.isClosed) {
          			s.cssSaved = false;
          			return;
          		}
          
          		var
          			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
          		,	curCSS	= {}
          		,	of		= $P.css("overflow")
          		,	ofX		= $P.css("overflowX")
          		,	ofY		= $P.css("overflowY")
          		;
          		// determine which, if any, overflow settings need to be changed
          		if (of != "visible") {
          			curCSS.overflow = of;
          			newCSS.overflow = "visible";
          		}
          		if (ofX && ofX != "visible" && ofX != "auto") {
          			curCSS.overflowX = ofX;
          			newCSS.overflowX = "visible";
          		}
          		if (ofY && ofY != "visible" && ofY != "auto") {
          			curCSS.overflowY = ofX;
          			newCSS.overflowY = "visible";
          		}
          
          		// save the current overflow settings - even if blank!
          		s.cssSaved = curCSS;
          
          		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
          		$P.css( newCSS );
          
          		// make sure the zIndex of all other panes is normal
          		$.each(c.allPanes.split(","), function(i, p) {
          			if (p != pane) resetOverflow(p);
          		});
          
          	};
          
          	function resetOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		,	CSS		= s.cssSaved || {}
          		;
          		// reset the zIndex
          		if (!s.isSliding && !s.isResizing)
          			$P.css("zIndex", c.zIndex.pane_normal);
          
          		// reset Overflow - if necessary
          		$P.css( CSS );
          
          		// clear var
          		s.cssSaved = false;
          	};
          
          
          	/**
          	* getBtn
          	*
          	* Helper function to validate params received by addButton utilities
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
          	*/
          	function getBtn(selector, pane, action) {
          		var
          			$E = $(selector)
          		,	err = "Error Adding Button \n\nInvalid "
          		;
          		if (!$E.length) // element not found
          			alert(err+"selector: "+ selector);
          		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
          			alert(err+"pane: "+ pane);
          		else { // VALID
          			var btn = options[pane].buttonClass +"-"+ action;
          			$E.addClass( btn +" "+ btn +"-"+ pane );
          			return $E;
          		}
          		return false;  // INVALID
          	};
          
          
          	/**
          	* addToggleBtn
          	*
          	* Add a custom Toggler button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addToggleBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "toggle");
          		if ($E)
          			$E
          				.attr("title", state[pane].isClosed ? "Open" : "Close")
          				.click(function (evt) {
          					toggle(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addOpenBtn
          	*
          	* Add a custom Open button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addOpenBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "open");
          		if ($E)
          			$E
          				.attr("title", "Open")
          				.click(function (evt) {
          					open(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addCloseBtn
          	*
          	* Add a custom Close button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addCloseBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "close");
          		if ($E)
          			$E
          				.attr("title", "Close")
          				.click(function (evt) {
          					close(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addPinBtn
          	*
          	* Add a custom Pin button for a pane
          	*
          	* Four classes are added to the element, based on the paneClass for the associated pane...
          	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
          	*  - ui-layout-pane-pin
          	*  - ui-layout-pane-west-pin
          	*  - ui-layout-pane-pin-up
          	*  - ui-layout-pane-west-pin-up
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
          	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
          	*/
          	function addPinBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "pin");
          		if ($E) {
          			var s = state[pane];
          			$E.click(function (evt) {
          				setPinState($(this), pane, (s.isSliding || s.isClosed));
          				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
          				else close( pane ); // slide-closed
          				evt.stopPropagation();
          			});
          			// add up/down pin attributes and classes
          			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
          			// add this pin to the pane data so we can 'sync it' automatically
          			// PANE.pins key is an array so we can store multiple pins for each pane
          			c[pane].pins.push( selector ); // just save the selector string
          		}
          	};
          
          	/**
          	* syncPinBtns
          	*
          	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
          	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
          	*
          	* @callers  open(), close()
          	* @params  pane   These are the params returned to callbacks by layout()
          	* @params  doPin  True means set the pin 'down', False means 'up'
          	*/
          	function syncPinBtns (pane, doPin) {
          		$.each(c[pane].pins, function (i, selector) {
          			setPinState($(selector), pane, doPin);
          		});
          	};
          
          	/**
          	* setPinState
          	*
          	* Change the class of the pin button to make it look 'up' or 'down'
          	*
          	* @callers  addPinBtn(), syncPinBtns()
          	* @param Element  $Pin		The pin-span element in a jQuery wrapper
          	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
          	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
          	*/
          	function setPinState ($Pin, pane, doPin) {
          		var updown = $Pin.attr("pin");
          		if (updown && doPin == (updown=="down")) return; // already in correct state
          		var
          			root	= options[pane].buttonClass
          		,	class1	= root +"-pin"
          		,	class2	= class1 +"-"+ pane
          		,	UP1		= class1 + "-up"
          		,	UP2		= class2 + "-up"
          		,	DN1		= class1 + "-down"
          		,	DN2		= class2 + "-down"
          		;
          		$Pin
          			.attr("pin", doPin ? "down" : "up") // logic
          			.attr("title", doPin ? "Un-Pin" : "Pin")
          			.removeClass( doPin ? UP1 : DN1 ) 
          			.removeClass( doPin ? UP2 : DN2 ) 
          			.addClass( doPin ? DN1 : UP1 ) 
          			.addClass( doPin ? DN2 : UP2 ) 
          		;
          	};
          
          
          /*
           * ###########################
           * CREATE/RETURN BORDER-LAYOUT
           * ###########################
           */
          
          	// init global vars
          	var 
          		$Container = $(this).css({ overflow: "hidden" }) // Container elem
          	,	$Ps		= {} // Panes x4	- set in initPanes()
          	,	$Cs		= {} // Content x4	- set in initPanes()
          	,	$Rs		= {} // Resizers x4	- set in initHandles()
          	,	$Ts		= {} // Togglers x4	- set in initHandles()
          	//	object aliases
          	,	c		= config // alias for config hash
          	,	cDims	= state.container // alias for easy access to 'container dimensions'
          	;
          
          	// create the border layout NOW
          	create();
          
          	// return object pointers to expose data & option Properties, and primary action Methods
          	return {
          		options:		options			// property - options hash
          	,	state:			state			// property - dimensions hash
          	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
          	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
          	,	open:			open			// method - ditto
          	,	close:			close			// method - ditto
          	,	hide:			hide			// method - ditto
          	,	show:			show			// method - ditto
          	,	resizeContent:	sizeContent		// method - ditto
          	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
          	,	resizeAll:		resizeAll		// method - no parameters
          	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
          	,	addOpenBtn:		addOpenBtn		// utility - ditto
          	,	addCloseBtn:	addCloseBtn		// utility - ditto
          	,	addPinBtn:		addPinBtn		// utility - ditto
          	,	allowOverflow:	allowOverflow	// utility - pass calling element
          	,	resetOverflow:	resetOverflow	// utility - ditto
          	,	cssWidth:		cssW
          	,	cssHeight:		cssH
          	};
          
          }
          })( jQuery );
          Evidence
          user
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        35. GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bWHERE\b and was detected in the element starting with: " initResizable(); // activate resizing on all panes where resizable=true ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (379 bytes)
          GET https://dev.duracloud.org/duradmin/jquery/plugins/jquery.layout.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 82920
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"82920-1230357900000"
          Last-Modified: Sat, 27 Dec 2008 06:05:00 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (82920 bytes)
          /*
           * jquery.layout 1.2.0
           *
           * Copyright (c) 2008 
           *   Fabrizio Balliano (http://www.fabrizioballiano.net)
           *   Kevin Dalman (http://allpro.net)
           *
           * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
           * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
           *
           * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
           * $Rev: 203 $
           * 
           * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
           */
          (function($) {
          
          $.fn.layout = function (opts) {
          
          /*
           * ###########################
           *   WIDGET CONFIG & OPTIONS
           * ###########################
           */
          
          	// DEFAULTS for options
          	var 
          		prefix = "ui-layout-" // prefix for ALL selectors and classNames
          	,	defaults = { //	misc default values
          			paneClass:				prefix+"pane"		// ui-layout-pane
          		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
          		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
          		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
          		,	buttonClass:			prefix+"button"		// ui-layout-button
          		,	contentSelector:		"."+prefix+"content"// ui-layout-content
          		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
          		}
          	;
          
          	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
          	var options = {
          		name:						""			// FUTURE REFERENCE - not used right now
          	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
          	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
          			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
          		,	closable:				true		// pane can open & close
          		,	resizable:				true		// when open, pane can be resized 
          		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
          		//,	paneSelector:			[ ]			// MUST be pane-specific!
          		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
          		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
          		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
          		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
          		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
          		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
          		,	resizerDragOpacity:		1			// option for ui.draggable
          		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
          		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
          		//,	size:					100			// inital size of pane - defaults are set 'per pane'
          		,	minSize:				0			// when manually resizing a pane
          		,	maxSize:				0			// ditto, 0 = no limit
          		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
          		,	spacing_closed:			6			// ditto - when pane is 'closed'
          		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
          		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
          		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
          		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
          		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
          		,	togglerTip_closed:		"Open"		// ditto
          		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
          		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
          		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
          		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
          		,	slideTrigger_close:		"mouseout"	// click, mouseout
          		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
          		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
          		,	togglerContent_closed:	""			// ditto
          		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
          		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
          		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
          		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
          		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
          		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
          		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
          		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
          		,	initClosed:				false		// true = init pane as 'closed'
          		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
          		
          		/*	callback options do not have to be set - listed here for reference only
          		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
          		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
          		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
          		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
          		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
          		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
          		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
          		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
          		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
          		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
          		*/
          		}
          	,	north: {
          			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
          		,	size:					"auto"
          		,	resizerCursor:			"n-resize"
          		}
          	,	south: {
          			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
          		,	size:					"auto"
          		,	resizerCursor:			"s-resize"
          		}
          	,	east: {
          			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
          		,	size:					200
          		,	resizerCursor:			"e-resize"
          		}
          	,	west: {
          			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
          		,	size:					200
          		,	resizerCursor:			"w-resize"
          		}
          	,	center: {
          			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
          		}
          
          	};
          
          
          	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
          		slide:	{
          			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	drop:	{
          			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
          		,	north:	{ direction: "up"	}
          		,	south:	{ direction: "down"	}
          		,	east:	{ direction: "right"}
          		,	west:	{ direction: "left"	}
          		}
          	,	scale:	{
          			all:	{ duration:  "fast"	}
          		}
          	};
          
          
          	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
          	var config = {
          		allPanes:		"north,south,east,west,center"
          	,	borderPanes:	"north,south,east,west"
          	,	zIndex: { // set z-index values here
          			resizer_normal:	1		// normal z-index for resizer-bars
          		,	pane_normal:	2		// normal z-index for panes
          		,	mask:			4		// overlay div used to mask pane(s) during resizing
          		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
          		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
          		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
          		}
          	,	resizers: {
          			cssReq: {
          				position: 	"absolute"
          			,	padding: 	0
          			,	margin: 	0
          			,	fontSize:	"1px"
          			,	textAlign:	"left" // to counter-act "center" alignment!
          			,	overflow: 	"hidden" // keep toggler button from overflowing
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#DDD"
          			,	border:		"none"
          			}
          		}
          	,	togglers: {
          			cssReq: {
          				position: 	"absolute"
          			,	display: 	"block"
          			,	padding: 	0
          			,	margin: 	0
          			,	overflow:	"hidden"
          			,	textAlign:	"center"
          			,	fontSize:	"1px"
          			,	cursor: 	"pointer"
          			,	zIndex: 	1
          			}
          		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
          				background: "#AAA"
          			}
          		}
          	,	content: {
          			cssReq: {
          				overflow:	"auto"
          			}
          		,	cssDef: {}
          		}
          	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
          			cssReq: {
          				position: 	"absolute"
          			,	margin:		0
          			,	zIndex: 	2
          			}
          		,	cssDef: {
          				padding:	"10px"
          			,	background:	"#FFF"
          			,	border:		"1px solid #BBB"
          			,	overflow:	"auto"
          			}
          		}
          	,	north: {
          			edge:			"top"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		0
          			,	bottom: 	"auto"
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	south: {
          			edge:			"bottom"
          		,	sizeType:		"height"
          		,	dir:			"horz"
          		,	cssReq: {
          				top: 		"auto"
          			,	bottom: 	0
          			,	left: 		0
          			,	right: 		0
          			,	width: 		"auto"
          			//	height: 	DYNAMIC
          			}
          		}
          	,	east: {
          			edge:			"right"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		"auto"
          			,	right: 		0
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	west: {
          			edge:			"left"
          		,	sizeType:		"width"
          		,	dir:			"vert"
          		,	cssReq: {
          				left: 		0
          			,	right: 		"auto"
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			//	width: 		DYNAMIC
          			}
          		}
          	,	center: {
          			dir:			"center"
          		,	cssReq: {
          				left: 		"auto" // DYNAMIC
          			,	right: 		"auto" // DYNAMIC
          			,	top: 		"auto" // DYNAMIC
          			,	bottom: 	"auto" // DYNAMIC
          			,	height: 	"auto"
          			,	width: 		"auto"
          			}
          		}
          	};
          
          
          	// DYNAMIC DATA
          	var state = {
          		// generate random 'ID#' to identify layout - used to create global namespace for timers
          		id:			Math.floor(Math.random() * 10000)
          	,	container:	{}
          	,	north:		{}
          	,	south:		{}
          	,	east:		{}
          	,	west:		{}
          	,	center:		{}
          	};
          
          
          	var 
          		altEdge = {
          			top:	"bottom"
          		,	bottom: "top"
          		,	left:	"right"
          		,	right:	"left"
          		}
          	,	altSide = {
          			north:	"south"
          		,	south:	"north"
          		,	east: 	"west"
          		,	west: 	"east"
          		}
          	;
          
          
          /*
           * ###########################
           *  INTERNAL HELPER FUNCTIONS
           * ###########################
           */
          
          	/**
          	 * isStr
          	 *
          	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
          	 */
          	var isStr = function (o) {
          		if (typeof o == "string")
          			return true;
          		else if (typeof o == "object") {
          			try {
          				var match = o.constructor.toString().match(/string/i); 
          				return (match !== null);
          			} catch (e) {} 
          		}
          		return false;
          	};
          
          	/**
          	 * str
          	 *
          	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
          	 *  else returns the original object
          	 */
          	var str = function (o) {
          		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
          		else return o;
          	};
          
          	/**
          	 * min / max
          	 *
          	 * Alias for Math.min/.max to simplify coding
          	 */
          	var min = function (x,y) { return Math.min(x,y); };
          	var max = function (x,y) { return Math.max(x,y); };
          
          	/**
          	 * transformData
          	 *
          	 * Processes the options passed in and transforms them into the format used by layout()
          	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
          	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
          	 * To update effects, options MUST use nested-keys format, with an effects key
          	 *
          	 * @callers  initOptions()
          	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
          	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
          	 */
          	var transformData = function (d) {
          		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
          		d = d || {};
          		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
          			json = $.extend( json, d ); // already in json format - add to base keys
          		else
          			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
          			$.each( d, function (key,val) {
          				a = key.split("__");
          				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
          			});
          		return json;
          	};
          
          	/**
          	 * setFlowCallback
          	 *
          	 * Set an INTERNAL callback to avoid simultaneous animation
          	 * Runs only if needed and only if all callbacks are not 'already set'!
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var setFlowCallback = function (action, pane, param) {
          		var
          			cb = action +","+ pane +","+ (param ? 1 : 0)
          		,	cP, cbPane
          		;
          		$.each(c.borderPanes.split(","), function (i,p) {
          			if (c[p].isMoving) {
          				bindCallback(p); // TRY to bind a callback
          				return false; // BREAK
          			}
          		});
          
          		function bindCallback (p, test) {
          			cP = c[p];
          			if (!cP.doCallback) {
          				cP.doCallback = true;
          				cP.callback = cb;
          			}
          			else { // try to 'chain' this callback
          				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
          				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
          					bindCallback (cpPane, true); // RECURSE
          			}
          		}
          	};
          
          	/**
          	 * execFlowCallback
          	 *
          	 * RUN the INTERNAL callback for this pane - if one exists
          	 *
          	 * @param String   action  Either 'open' or 'close'
          	 * @pane  String   pane    A valid border-pane name, eg 'west'
          	 * @pane  Boolean  param   Extra param for callback (optional)
          	 */
          	var execFlowCallback = function (pane) {
          		var cP = c[pane];
          
          		// RESET flow-control flaGs
          		c.isLayoutBusy = false;
          		delete cP.isMoving;
          		if (!cP.doCallback || !cP.callback) return;
          
          		cP.doCallback = false; // RESET logic flag
          
          		// EXECUTE the callback
          		var
          			cb = cP.callback.split(",")
          		,	param = (cb[2] > 0 ? true : false)
          		;
          		if (cb[0] == "open")
          			open( cb[1], param  );
          		else if (cb[0] == "close")
          			close( cb[1], param );
          
          		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
          	};
          
          	/**
          	 * execUserCallback
          	 *
          	 * Executes a Callback function after a trigger event, like resize, open or close
          	 *
          	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
          	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
          	 */
          	var execUserCallback = function (pane, v_fn) {
          		if (!v_fn) return;
          		var fn;
          		try {
          			if (typeof v_fn == "function")
          				fn = v_fn;	
          			else if (typeof v_fn != "string")
          				return;
          			else if (v_fn.indexOf(",") > 0) {
          				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
          				var
          					args = v_fn.split(",")
          				,	fn = eval(args[0])
          				;
          				if (typeof fn=="function" && args.length > 1)
          					return fn(args[1]); // pass the argument parsed from 'list'
          			}
          			else // just the name of an external function?
          				fn = eval(v_fn);
          
          			if (typeof fn=="function")
          				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
          				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
          		}
          		catch (ex) {}
          	};
          
          	/**
          	 * cssNum
          	 *
          	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
          	 *
          	 * @callers  Called by many methods
          	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
          	 * @param String  property  The name of the CSS property, eg: top, width, etc.
          	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
          	 */
          	var cssNum = function ($E, prop) {
          		var
          			val = 0
          		,	hidden = false
          		,	visibility = ""
          		;
          		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
          			if ($.curCSS($E[0], "display", true) == "none") {
          				hidden = true;
          				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
          				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
          			}
          		}
          
          		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
          
          		if (hidden) { // WAS hidden, so put back the way it was
          			$E.css({ display: "none" });
          			if (visibility && visibility != "hidden")
          				$E.css({ visibility: visibility }); // reset 'visibility'
          		}
          
          		return val;
          	};
          
          	/**
          	 * cssW / cssH / cssSize
          	 *
          	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
          	 *
          	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
          	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
          	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
          	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
          	 *
          	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
          	 */
          	var cssW = function (e, outerWidth) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerWidth <= 0)
          			return 0;
          		else if (!(outerWidth>0))
          			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
          
          		if (!$.boxModel)
          			return outerWidth;
          
          		else // strip border and padding size from outerWidth to get CSS Width
          			return outerWidth
          				- cssNum($E, "paddingLeft")		
          				- cssNum($E, "paddingRight")
          				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
          				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
          			;
          	};
          	var cssH = function (e, outerHeight) {
          		var $E;
          		if (isStr(e)) {
          			e = str(e);
          			$E = $Ps[e];
          		}
          		else
          			$E = $(e);
          
          		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
          		if (outerHeight <= 0)
          			return 0;
          		else if (!(outerHeight>0))
          			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
          
          		if (!$.boxModel)
          			return outerHeight;
          
          		else // strip border and padding size from outerHeight to get CSS Height
          			return outerHeight
          				- cssNum($E, "paddingTop")
          				- cssNum($E, "paddingBottom")
          				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
          				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
          			;
          	};
          	var cssSize = function (pane, outerSize) {
          		if (c[pane].dir=="horz") // pane = north or south
          			return cssH(pane, outerSize);
          		else // pane = east or west
          			return cssW(pane, outerSize);
          	};
          
          	/**
          	 * getPaneSize
          	 *
          	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
          	 *
          	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
          	 */
          	var getPaneSize = function (pane, inclSpace) {
          		var 
          			$P	= $Ps[pane]
          		,	o	= options[pane]
          		,	s	= state[pane]
          		,	oSp	= (inclSpace ? o.spacing_open : 0)
          		,	cSp	= (inclSpace ? o.spacing_closed : 0)
          		;
          		if (!$P || s.isHidden)
          			return 0;
          		else if (s.isClosed || (s.isSliding && inclSpace))
          			return cSp;
          		else if (c[pane].dir == "horz")
          			return $P.outerHeight() + oSp;
          		else // dir == "vert"
          			return $P.outerWidth() + oSp;
          	};
          
          	var setPaneMinMaxSizes = function (pane) {
          		var 
          			d				= cDims
          		,	edge			= c[pane].edge
          		,	dir				= c[pane].dir
          		,	o				= options[pane]
          		,	s				= state[pane]
          		,	$P				= $Ps[pane]
          		,	$altPane		= $Ps[ altSide[pane] ]
          		,	paneSpacing		= o.spacing_open
          		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
          		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
          		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
          		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
          		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
          		,	minSize			= s.minSize || 0
          		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
          		,	minPos, maxPos	// used to set resizing limits
          		;
          		switch (pane) {
          			case "north":	minPos = d.offsetTop + minSize;
          							maxPos = d.offsetTop + maxSize;
          							break;
          			case "west":	minPos = d.offsetLeft + minSize;
          							maxPos = d.offsetLeft + maxSize;
          							break;
          			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
          							maxPos = d.offsetTop + d.innerHeight - minSize;
          							break;
          			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
          							maxPos = d.offsetLeft + d.innerWidth - minSize;
          							break;
          		}
          		// save data to pane-state
          		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
          	};
          
          	/**
          	 * getPaneDims
          	 *
          	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
          	 *
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
          	 */
          	var getPaneDims = function () {
          		var d = {
          			top:	getPaneSize("north", true) // true = include 'spacing' value for p
          		,	bottom:	getPaneSize("south", true)
          		,	left:	getPaneSize("west", true)
          		,	right:	getPaneSize("east", true)
          		,	width:	0
          		,	height:	0
          		};
          
          		with (d) {
          			width 	= cDims.innerWidth - left - right;
          			height 	= cDims.innerHeight - bottom - top;
          			// now add the 'container border/padding' to get final positions - relative to the container
          			top		+= cDims.top;
          			bottom	+= cDims.bottom;
          			left	+= cDims.left;
          			right	+= cDims.right;
          		}
          
          		return d;
          	};
          
          
          	/**
          	 * getElemDims
          	 *
          	 * Returns data for setting size of an element (container or a pane).
          	 *
          	 * @callers  create(), onWindowResize() for container, plus others for pane
          	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
          	 */
          	var getElemDims = function ($E) {
          		var
          			d = {} // dimensions hash
          		,	e, b, p // edge, border, padding
          		;
          
          		$.each("Left,Right,Top,Bottom".split(","), function () {
          			e = str(this);
          			b = d["border" +e] = cssNum($E, "border"+e+"Width");
          			p = d["padding"+e] = cssNum($E, "padding"+e);
          			d["offset" +e] = b + p; // total offset of content from outer edge
          			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
          			if ($E == $Container)
          				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
          		});
          
          		d.innerWidth  = d.outerWidth  = $E.outerWidth();
          		d.innerHeight = d.outerHeight = $E.outerHeight();
          		if ($.boxModel) {
          			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
          			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
          		}
          
          		return d;
          	};
          
          
          	var setTimer = function (pane, action, fn, ms) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) return; // timer already set!
          		else Timers[name] = setTimeout(fn, ms);
          	};
          
          	var clearTimer = function (pane, action) {
          		var
          			Layout = window.layout = window.layout || {}
          		,	Timers = Layout.timers = Layout.timers || {}
          		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
          		;
          		if (Timers[name]) {
          			clearTimeout( Timers[name] );
          			delete Timers[name];
          			return true;
          		}
          		else
          			return false;
          	};
          
          
          /*
           * ###########################
           *   INITIALIZATION METHODS
           * ###########################
           */
          
          	/**
          	 * create
          	 *
          	 * Initialize the layout - called automatically whenever an instance of layout is created
          	 *
          	 * @callers  NEVER explicity called
          	 * @returns  An object pointer to the instance created
          	 */
          	var create = function () {
          		// initialize config/options
          		initOptions();
          
          		// initialize all objects
          		initContainer();	// set CSS as needed and init state.container dimensions
          		initPanes();		// size & position all panes
          		initHandles();		// create and position all resize bars & togglers buttons
          		initResizable();	// activate resizing on all panes where resizable=true
          		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
          
          		if (options.scrollToBookmarkOnLoad)
          			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
          
          		// bind hotkey function - keyDown - if required
          		initHotkeys();
          
          		// bind resizeAll() for 'this layout instance' to window.resize event
          		$(window).resize(function () {
          			var timerID = "timerLayout_"+state.id;
          			if (window[timerID]) clearTimeout(window[timerID]);
          			window[timerID] = null;
          			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
          				window[timerID] = setTimeout(resizeAll, 100);
          			else // most other browsers have a built-in delay before firing the resize event
          				resizeAll(); // resize all layout elements NOW!
          		});
          	};
          
          	/**
          	 * initContainer
          	 *
          	 * Validate and initialize container CSS and events
          	 *
          	 * @callers  create()
          	 */
          	var initContainer = function () {
          		try { // format html/body if this is a full page layout
          			if ($Container[0].tagName == "BODY") {
          				$("html").css({
          					height:		"100%"
          				,	overflow:	"hidden"
          				});
          				$("body").css({
          					position:	"relative"
          				,	height:		"100%"
          				,	overflow:	"hidden"
          				,	margin:		0
          				,	padding:	0		// TODO: test whether body-padding could be handled?
          				,	border:		"none"	// a body-border creates problems because it cannot be measured!
          				});
          			}
          			else { // set required CSS - overflow and position
          				var
          					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
          				,	p	= $Container.css("position")
          				,	h	= $Container.css("height")
          				;
          				// if this is a NESTED layout, then outer-pane ALREADY has position and height
          				if (!$Container.hasClass("ui-layout-pane")) {
          					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
          						CSS.position = "relative"; // container MUST have a 'position'
          					if (!h || h=="auto")
          						CSS.height = "100%"; // container MUST have a 'height'
          				}
          				$Container.css( CSS );
          			}
          		} catch (ex) {}
          
          		// get layout-container dimensions (updated when necessary)
          		cDims = state.container = getElemDims( $Container ); // update data-pointer too
          	};
          
          	/**
          	 * initHotkeys
          	 *
          	 * Bind layout hotkeys - if options enabled
          	 *
          	 * @callers  create()
          	 */
          	var initHotkeys = function () {
          		// bind keyDown to capture hotkeys, if option enabled for ANY pane
          		$.each(c.borderPanes.split(","), function (i,pane) {
          			var o = options[pane];
          			if (o.enableCursorHotkey || o.customHotkey) {
          				$(document).keydown( keyDown ); // only need to bind this ONCE
          				return false; // BREAK - binding was done
          			}
          		});
          	};
          
          	/**
          	 * initOptions
          	 *
          	 * Build final CONFIG and OPTIONS data
          	 *
          	 * @callers  create()
          	 */
          	var initOptions = function () {
          		// simplify logic by making sure passed 'opts' var has basic keys
          		opts = transformData( opts );
          
          		// update default effects, if case user passed key
          		if (opts.effects) {
          			$.extend( effects, opts.effects );
          			delete opts.effects;
          		}
          
          		// see if any 'global options' were specified
          		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
          			if (opts[key] !== undefined)
          				options[key] = opts[key];
          			else if (opts.defaults[key] !== undefined) {
          				options[key] = opts.defaults[key];
          				delete opts.defaults[key];
          			}
          		});
          
          		// remove any 'defaults' that MUST be set 'per-pane'
          		$.each("paneSelector,resizerCursor,customHotkey".split(","),
          			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
          		);
          
          		// now update options.defaults
          		$.extend( options.defaults, opts.defaults );
          		// make sure required sub-keys exist
          		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
          
          		// merge all config & options for the 'center' pane
          		c.center = $.extend( true, {}, c.defaults, c.center );
          		$.extend( options.center, opts.center );
          		// Most 'default options' do not apply to 'center', so add only those that DO
          		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
          		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
          			function (idx,key) { options.center[key] = o_Center[key]; }
          		);
          
          		var defs = options.defaults;
          
          		// create a COMPLETE set of options for EACH border-pane
          		$.each(c.borderPanes.split(","), function(i,pane) {
          			// apply 'pane-defaults' to CONFIG.PANE
          			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
          			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
          			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
          
          			// make sure we have base-classes
          			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
          			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
          			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
          
          			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
          			$.each(["_open","_close",""], function (i,n) { 
          				var
          					sName		= "fxName"+n
          				,	sSpeed		= "fxSpeed"+n
          				,	sSettings	= "fxSettings"+n
          				;
          				// recalculate fxName according to specificity rules
          				o[sName] =
          					opts[pane][sName]		// opts.west.fxName_open
          				||	opts[pane].fxName		// opts.west.fxName
          				||	opts.defaults[sName]	// opts.defaults.fxName_open
          				||	opts.defaults.fxName	// opts.defaults.fxName
          				||	o[sName]				// options.west.fxName_open
          				||	o.fxName				// options.west.fxName
          				||	defs[sName]				// options.defaults.fxName_open
          				||	defs.fxName				// options.defaults.fxName
          				||	"none"
          				;
          				// validate fxName to be sure is a valid effect
          				var fxName = o[sName];
          				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
          					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
          				// set vars for effects subkeys to simplify logic
          				var
          					fx = effects[fxName]	|| {} // effects.slide
          				,	fx_all	= fx.all		|| {} // effects.slide.all
          				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
          				;
          				// RECREATE the fxSettings[_open|_close] keys using specificity rules
          				o[sSettings] = $.extend(
          					{}
          				,	fx_all						// effects.slide.all
          				,	fx_pane						// effects.slide.west
          				,	defs.fxSettings || {}		// options.defaults.fxSettings
          				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
          				,	o.fxSettings				// options.west.fxSettings
          				,	o[sSettings]				// options.west.fxSettings_open
          				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
          				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
          				,	opts[pane].fxSettings		// opts.west.fxSettings
          				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
          				);
          				// recalculate fxSpeed according to specificity rules
          				o[sSpeed] =
          					opts[pane][sSpeed]		// opts.west.fxSpeed_open
          				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
          				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
          				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
          				||	o[sSpeed]				// options.west.fxSpeed_open
          				||	o[sSettings].duration	// options.west.fxSettings_open.duration
          				||	o.fxSpeed				// options.west.fxSpeed
          				||	o.fxSettings.duration	// options.west.fxSettings.duration
          				||	defs.fxSpeed			// options.defaults.fxSpeed
          				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
          				||	fx_pane.duration		// effects.slide.west.duration
          				||	fx_all.duration			// effects.slide.all.duration
          				||	"normal"				// DEFAULT
          				;
          				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
          			});
          		});
          	};
          
          	/**
          	 * initPanes
          	 *
          	 * Initialize module objects, styling, size and position for all panes
          	 *
          	 * @callers  create()
          	 */
          	var initPanes = function () {
          		// NOTE: do north & south FIRST so we can measure their height - do center LAST
          		$.each(c.allPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	fx		= s.fx
          			,	dir		= c[pane].dir
          			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
          			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
          			,	minSize	= o.minSize || 1
          			,	maxSize	= o.maxSize || 9999
          			,	spacing	= o.spacing_open || 0
          			,	sel		= o.paneSelector
          			,	isIE6	= ($.browser.msie && $.browser.version < 7)
          			,	CSS		= {}
          			,	$P, $C
          			;
          			$Cs[pane] = false; // init
          
          			if (sel.substr(0,1)==="#") // ID selector
          				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
          				$P = $Ps[pane] = $Container.find(sel+":first");
          			else { // class or other selector
          				$P = $Ps[pane] = $Container.children(sel+":first");
          				// look for the pane nested inside a 'form' element
          				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
          			}
          
          			if (!$P.length) {
          				$Ps[pane] = false; // logic
          				return true; // SKIP to next
          			}
          
          			// add basic classes & attributes
          			$P
          				.attr("pane", pane) // add pane-identifier
          				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
          			;
          
          			// init pane-logic vars, etc.
          			if (pane != "center") {
          				s.isClosed  = false; // true = pane is closed
          				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
          				s.isResizing= false; // true = pane is in process of being resized
          				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
          				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
          				// create special keys for internal use
          				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
          			}
          
          			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
          			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
          			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
          			CSS = {};	// reset var
          
          			// set css-position to account for container borders & padding
          			switch (pane) {
          				case "north": 	CSS.top 	= cDims.top;
          								CSS.left 	= cDims.left;
          								CSS.right	= cDims.right;
          								break;
          				case "south": 	CSS.bottom	= cDims.bottom;
          								CSS.left 	= cDims.left;
          								CSS.right 	= cDims.right;
          								break;
          				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
          								break;
          				case "east": 	CSS.right 	= cDims.right; // ditto
          								break;
          				case "center":	// top, left, width & height set by sizeMidPanes()
          			}
          
          			if (dir == "horz") { // north or south pane
          				if (size === 0 || size == "auto") {
          					$P.css({ height: "auto" });
          					size = $P.outerHeight();
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerHeight - spacing);
          				CSS.height = max(1, cssH(pane, size));
          				s.size = size; // update state
          				// make sure minSize is sufficient to avoid errors
          				s.maxSize = maxSize; // init value
          				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
          				// handle IE6
          				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
          				$P.css(CSS); // apply size & position
          			}
          			else if (dir == "vert") { // east or west pane
          				if (size === 0 || size == "auto") {
          					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
          					size = $P.outerWidth();
          					$P.css({ float: "none" }); // RESET
          				}
          				size = max(size, minSize);
          				size = min(size, maxSize);
          				size = min(size, cDims.innerWidth - spacing);
          				CSS.width = max(1, cssW(pane, size));
          				s.size = size; // update state
          				s.maxSize = maxSize; // init value
          				// make sure minSize is sufficient to avoid errors
          				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
          				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
          				sizeMidPanes(pane, null, true); // true = onInit
          			}
          			else if (pane == "center") {
          				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
          				sizeMidPanes("center", null, true); // true = onInit
          			}
          
          			// close or hide the pane if specified in settings
          			if (o.initClosed && o.closable) {
          				$P.hide().addClass("closed");
          				s.isClosed = true;
          			}
          			else if (o.initHidden || o.initClosed) {
          				hide(pane, true); // will be completely invisible - no resizer or spacing
          				s.isHidden = true;
          			}
          			else
          				$P.addClass("open");
          
          			// check option for auto-handling of pop-ups & drop-downs
          			if (o.showOverflowOnHover)
          				$P.hover( allowOverflow, resetOverflow );
          
          			/*
          			 *	see if this pane has a 'content element' that we need to auto-size
          			 */
          			if (o.contentSelector) {
          				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
          				if (!$C.length) {
          					$Cs[pane] = false;
          					return true; // SKIP to next
          				}
          				$C.css( c.content.cssReq );
          				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
          				// NO PANE-SCROLLING when there is a content-div
          				$P.css({ overflow: "hidden" });
          			}
          		});
          	};
          
          	/**
          	 * initHandles
          	 *
          	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
          	 *
          	 * @callers  create()
          	 */
          	var initHandles = function () {
          		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	rClass	= o.resizerClass
          			,	tClass	= o.togglerClass
          			,	$P		= $Ps[pane]
          			;
          			$Rs[pane] = false; // INIT
          			$Ts[pane] = false;
          
          			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
          
          			var 
          				edge	= c[pane].edge
          			,	isOpen	= $P.is(":visible")
          			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
          			,	_pane	= "-"+ pane // used for classNames
          			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
          			,	$R, $T
          			;
          			// INIT RESIZER BAR
          			$R = $Rs[pane] = $("<span></span>");
          	
          			if (isOpen && o.resizable)
          				; // this is handled by initResizable
          			else if (!isOpen && o.slidable)
          				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
          	
          			$R
          				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
          				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
          				.attr("resizer", pane) // so we can read this from the resizer
          				.css(c.resizers.cssReq) // add base/required styles
          				// POSITION of resizer bar - allow for container border & padding
          				.css(edge, cDims[edge] + getPaneSize(pane))
          				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
          				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
          				.appendTo($Container) // append DIV to container
          			;
          			 // ADD VISUAL STYLES
          			if (o.applyDefaultStyles)
          				$R.css(c.resizers.cssDef);
          
          			if (o.closable) {
          				// INIT COLLAPSER BUTTON
          				$T = $Ts[pane] = $("<div></div>");
          				$T
          					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
          					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
          					.css(c.togglers.cssReq) // add base/required styles
          					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
          					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
          					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
          					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
          					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
          					.appendTo($R) // append SPAN to resizer DIV
          				;
          
          				// ADD INNER-SPANS TO TOGGLER
          				if (o.togglerContent_open) // ui-layout-open
          					$("<span>"+ o.togglerContent_open +"</span>")
          						.addClass("content content-open")
          						.css("display", s.isClosed ? "none" : "block")
          						.appendTo( $T )
          					;
          				if (o.togglerContent_closed) // ui-layout-closed
          					$("<span>"+ o.togglerContent_closed +"</span>")
          						.addClass("content content-closed")
          						.css("display", s.isClosed ? "block" : "none")
          						.appendTo( $T )
          					;
          
          				 // ADD BASIC VISUAL STYLES
          				if (o.applyDefaultStyles)
          					$T.css(c.togglers.cssDef);
          
          				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          			}
          
          		});
          
          		// SET ALL HANDLE SIZES & LENGTHS
          		sizeHandles("all", true); // true = onInit
          	};
          
          	/**
          	 * initResizable
          	 *
          	 * Add resize-bars to all panes that specify it in options
          	 *
          	 * @dependancies  $.fn.resizable - will abort if not found
          	 * @callers  create()
          	 */
          	var initResizable = function () {
          		var
          			draggingAvailable = (typeof $.fn.draggable == "function")
          		,	minPosition, maxPosition, edge // set in start()
          		;
          
          		$.each(c.borderPanes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			;
          			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
          				o.resizable = false;
          				return true; // skip to next
          			}
          
          			var 
          				rClass				= o.resizerClass
          			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
          			,	dragClass			= rClass+"-drag"			// resizer-drag
          			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
          			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
          			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
          			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
          			,	draggingClassSet	= false 					// logic var
          			,	$P 					= $Ps[pane]
          			,	$R					= $Rs[pane]
          			;
          
          			if (!s.isClosed)
          				$R
          					.attr("title", o.resizerTip)
          					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
          				;
          
          			$R.draggable({
          				containment:	$Container[0] // limit resizing to layout container
          			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
          			,	delay:			200
          			,	distance:		1
          			//	basic format for helper - style it using class: .ui-draggable-dragging
          			,	helper:			"clone"
          			,	opacity:		o.resizerDragOpacity
          			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
          			,	zIndex:			c.zIndex.resizing
          
          			,	start: function (e, ui) {
          					// onresize_start callback - will CANCEL hide if returns false
          					// TODO: CONFIRM that dragging can be cancelled like this???
          					if (false === execUserCallback(pane, o.onresize_start)) return false;
          
          					s.isResizing = true; // prevent pane from closing while resizing
          					clearTimer(pane, "closeSlider"); // just in case already triggered
          
          					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
          					draggingClassSet = false; // reset logic var - see drag()
          
          					// SET RESIZING LIMITS - used in drag()
          					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
          					setPaneMinMaxSizes(pane); // update pane-state
          					s.minPosition -= resizerWidth;
          					s.maxPosition -= resizerWidth;
          					edge = (c[pane].dir=="horz" ? "top" : "left");
          
          					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
          					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
          						$('<div class="ui-layout-mask"/>')
          							.css({
          								background:	"#fff"
          							,	opacity:	"0.001"
          							,	zIndex:		9
          							,	position:	"absolute"
          							,	width:		this.offsetWidth+"px"
          							,	height:		this.offsetHeight+"px"
          							})
          							.css($(this).offset()) // top & left
          							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
          						;
          					});
          				}
          
          			,	drag: function (e, ui) {
          					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
          						$(".ui-draggable-dragging")
          							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
          							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
          						;
          						draggingClassSet = true;
          						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
          						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
          					}
          					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
          					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
          					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
          				}
          
          			,	stop: function (e, ui) {
          					var 
          						dragPos	= ui.position
          					,	resizerPos
          					,	newSize
          					;
          					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
          	
          					switch (pane) {
          						case "north":	resizerPos = dragPos.top; break;
          						case "west":	resizerPos = dragPos.left; break;
          						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
          						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
          					}
          					// remove container margin from resizer position to get the pane size
          					newSize = resizerPos - cDims[ c[pane].edge ];
          
          					sizePane(pane, newSize);
          
          					// UN-MASK PANES MASKED IN drag.start
          					$("div.ui-layout-mask").remove(); // Remove iframe masks	
          
          					s.isResizing = false;
          				}
          
          			});
          		});
          	};
          
          
          
          /*
           * ###########################
           *       ACTION METHODS
           * ###########################
           */
          
          	/**
          	 * hide / show
          	 *
          	 * Completely 'hides' a pane, including its spacing - as if it does not exist
          	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
          	 *
          	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
          	 */
          	var hide = function (pane, onInit) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onhide_start)) return;
          
          		s.isSliding = false; // just in case
          
          		// now hide the elements
          		if ($R) $R.hide(); // hide resizer-bar
          		if (onInit || s.isClosed) {
          			s.isClosed = true; // to trigger open-animation on show()
          			s.isHidden  = true;
          			$P.hide(); // no animation when loading page
          			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          			execUserCallback(pane, o.onhide_end || o.onhide);
          		}
          		else {
          			s.isHiding = true; // used by onclose
          			close(pane, false); // adjust all panes to fit
          			//s.isHidden  = true; - will be set by close - if not cancelled
          		}
          	};
          
          	var show = function (pane, openPane) {
          		var
          			o	= options[pane]
          		,	s	= state[pane]
          		,	$P	= $Ps[pane]
          		,	$R	= $Rs[pane]
          		;
          		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
          
          		// onhide_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onshow_start)) return;
          
          		s.isSliding = false; // just in case
          		s.isShowing = true; // used by onopen/onclose
          		//s.isHidden  = false; - will be set by open/close - if not cancelled
          
          		// now show the elements
          		if ($R && o.spacing_open > 0) $R.show();
          		if (openPane === false)
          			close(pane, true); // true = force
          		else
          			open(pane); // adjust all panes to fit
          	};
          
          
          	/**
          	 * toggle
          	 *
          	 * Toggles a pane open/closed by calling either open or close
          	 *
          	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
          	 */
          	var toggle = function (pane) {
          		var s = state[pane];
          		if (s.isHidden)
          			show(pane); // will call 'open' after unhiding it
          		else if (s.isClosed)
          			open(pane);
          		else
          			close(pane);
          	};
          
          	/**
          	 * close
          	 *
          	 * Close the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being closed, ie: north, south, east, or west
          	 */
          	var close = function (pane, force, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_sliding= "-sliding"
          		,	_closed	= "-closed"
          		// 	transfer logic vars to temp vars
          		,	isShowing = s.isShowing
          		,	isHiding = s.isHiding
          		;
          		// now clear the logic vars
          		delete s.isShowing;
          		delete s.isHiding;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!force && s.isClosed && !isShowing) return; // already closed
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("close", pane, force); // set a callback for this action, if possible
          			return; // ABORT 
          		}
          
          		// onclose_start callback - will CANCEL hide if returns false
          		// SKIP if just 'showing' a hidden pane as 'closed'
          		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		s.isClosed = true;
          		// update isHidden BEFORE sizing panes
          		if (isHiding) s.isHidden = true;
          		else if (isShowing) s.isHidden = false;
          
          		// sync any 'pin buttons'
          		syncPinBtns(pane, false);
          
          		// resize panes adjacent to this one
          		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
          
          		// if this pane has a resizer bar, move it now
          		if ($R) {
          			$R
          				.css(edge, cDims[edge]) // move the resizer bar
          				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
          				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
          				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
          			;
          			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
          			if (o.resizable)
          				$R
          					.draggable("disable")
          					.css("cursor", "default")
          					.attr("title","")
          				;
          			// if pane has a toggler button, adjust that too
          			if ($T) {
          				$T
          					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
          					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
          					.attr("title", o.togglerTip_closed) // may be blank
          				;
          			}
          			sizeHandles(); // resize 'length' and position togglers for adjacent panes
          		}
          
          		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
          		if (doFX) {
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
          				lockPaneForFX(pane, false); // undo
          				if (!s.isClosed) return; // pane was opened before animation finished!
          				close_2();
          			});
          		}
          		else {
          			$P.hide(); // just hide pane NOW
          			close_2();
          		}
          
          		// SUBROUTINE
          		function close_2 () {
          			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
          
          			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
          			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
          			// onhide OR onshow callback
          			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
          			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          
          	/**
          	 * open
          	 *
          	 * Open the specified pane (animation optional), and resize all other panes as needed
          	 *
          	 * @param String  pane   The pane being opened, ie: north, south, east, or west
          	 */
          	var open = function (pane, slide, noAnimation) {
          		var 
          			$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		,	$T		= $Ts[pane]
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
          		,	edge	= c[pane].edge
          		,	rClass	= o.resizerClass
          		,	tClass	= o.togglerClass
          		,	_pane	= "-"+ pane // used for classNames
          		,	_open	= "-open"
          		,	_closed	= "-closed"
          		,	_sliding= "-sliding"
          		// 	transfer logic var to temp var
          		,	isShowing = s.isShowing
          		;
          		// now clear the logic var
          		delete s.isShowing;
          
          		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
          		else if (!s.isClosed && !s.isSliding) return; // already open
          
          		// pane can ALSO be unhidden by just calling show(), so handle this scenario
          		if (s.isHidden && !isShowing) {
          			show(pane, true);
          			return;
          		}
          
          		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
          			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
          			return; // ABORT
          		}
          
          		// onopen_start callback - will CANCEL hide if returns false
          		if (false === execUserCallback(pane, o.onopen_start)) return;
          
          		// SET flow-control flags
          		c[pane].isMoving = true;
          		c.isLayoutBusy = true;
          
          		// 'PIN PANE' - stop sliding
          		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
          			bindStopSlidingEvents(pane, false); // will set isSliding=false
          
          		s.isClosed = false;
          		// update isHidden BEFORE sizing panes
          		if (isShowing) s.isHidden = false;
          
          		// Container size may have changed - shrink the pane if now 'too big'
          		setPaneMinMaxSizes(pane); // update pane-state
          		if (s.size > s.maxSize) // pane is too big! resize it before opening
          			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
          
          		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
          
          		if (doFX) { // ANIMATE
          			lockPaneForFX(pane, true); // need to set left/top so animation will work
          			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
          				lockPaneForFX(pane, false); // undo
          				if (s.isClosed) return; // pane was closed before animation finished!
          				open_2(); // continue
          			});
          		}
          		else {// no animation
          			$P.show();	// just show pane and...
          			open_2();	// continue
          		}
          
          		// SUBROUTINE
          		function open_2 () {
          			// NOTE: if isSliding, then other panes are NOT 'resized'
          			if (!s.isSliding) // resize all panes adjacent to this one
          				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
          
          			// if this pane has a toggler, move it now
          			if ($R) {
          				$R
          					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
          					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
          					.addClass( rClass+_open +" "+ rClass+_pane+_open )
          					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
          				;
          				if (o.resizable)
          					$R
          						.draggable("enable")
          						.css("cursor", o.resizerCursor)
          						.attr("title", o.resizerTip)
          					;
          				else
          					$R.css("cursor", "default"); // n-resize, s-resize, etc
          				// if pane also has a toggler button, adjust that too
          				if ($T) {
          					$T
          						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
          						.addClass( tClass+_open +" "+ tClass+_pane+_open )
          						.attr("title", o.togglerTip_open) // may be blank
          					;
          				}
          				sizeHandles("all"); // resize resizer & toggler sizes for all panes
          			}
          
          			// resize content every time pane opens - to be sure
          			sizeContent(pane);
          
          			// sync any 'pin buttons'
          			syncPinBtns(pane, !s.isSliding);
          
          			// onopen callback
          			execUserCallback(pane, o.onopen_end || o.onopen);
          
          			// onshow callback
          			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
          
          			// internal flow-control callback
          			execFlowCallback(pane);
          		}
          	};
          	
          
          	/**
          	 * lockPaneForFX
          	 *
          	 * Must set left/top on East/South panes so animation will work properly
          	 *
          	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
          	 * @param Boolean  doLock  true = set left/top, false = remove
          	 */
          	var lockPaneForFX = function (pane, doLock) {
          		var $P = $Ps[pane];
          		if (doLock) {
          			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
          			if (pane=="south")
          				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
          			else if (pane=="east")
          				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
          		}
          		else {
          			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
          			if (pane=="south")
          				$P.css({ top: "auto" });
          			else if (pane=="east")
          				$P.css({ left: "auto" });
          		}
          	};
          
          
          	/**
          	 * bindStartSlidingEvent
          	 *
          	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
          	 *
          	 * @callers  open(), close()
          	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
          	 * @param Boolean  enable  Enable or Disable sliding?
          	 */
          	var bindStartSlidingEvent = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	$R		= $Rs[pane]
          		,	trigger	= o.slideTrigger_open
          		;
          		if (!$R || !o.slidable) return;
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
          		$R
          			// add or remove trigger event
          			[enable ? "bind" : "unbind"](trigger, slideOpen)
          			// set the appropriate cursor & title/tip
          			.css("cursor", (enable ? o.sliderCursor: "default"))
          			.attr("title", (enable ? o.sliderTip : ""))
          		;
          	};
          
          	/**
          	 * bindStopSlidingEvents
          	 *
          	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
          	 * Also increases zIndex when pane is sliding open
          	 * See bindStartSlidingEvent for code to control 'slide open'
          	 *
          	 * @callers  slideOpen(), slideClosed()
          	 * @param String  pane  The pane to process, 'north', 'south', etc.
          	 * @param Boolean  isOpen  Is pane open or closed?
          	 */
          	var bindStopSlidingEvents = function (pane, enable) {
          		var 
          			o		= options[pane]
          		,	s		= state[pane]
          		,	trigger	= o.slideTrigger_close
          		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          
          		s.isSliding = enable; // logic
          		clearTimer(pane, "closeSlider"); // just in case
          
          		// raise z-index when sliding
          		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
          		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
          
          		// make sure we have a valid event
          		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
          
          		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
          		if (enable) { // BIND trigger events
          			$P.bind(trigger, slideClosed );
          			$R.bind(trigger, slideClosed );
          			if (trigger = "mouseout") {
          				$P.bind("mouseover", cancelMouseOut );
          				$R.bind("mouseover", cancelMouseOut );
          			}
          		}
          		else { // UNBIND trigger events
          			// TODO: why does unbind of a 'single function' not work reliably?
          			//$P[action](trigger, slideClosed );
          			$P.unbind(trigger);
          			$R.unbind(trigger);
          			if (trigger = "mouseout") {
          				//$P[action]("mouseover", cancelMouseOut );
          				$P.unbind("mouseover");
          				$R.unbind("mouseover");
          				clearTimer(pane, "closeSlider");
          			}
          		}
          
          		// SUBROUTINE for mouseout timer clearing
          		function cancelMouseOut (evt) {
          			clearTimer(pane, "closeSlider");
          			evt.stopPropagation();
          		}
          	};
          
          	var slideOpen = function () {
          		var pane = $(this).attr("resizer"); // attr added by initHandles
          		if (state[pane].isClosed) { // skip if already open!
          			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
          			open(pane, true); // true = slide - ie, called from here!
          		}
          	};
          
          	var slideClosed = function () {
          		var
          			$E = $(this)
          		,	pane = $E.attr("pane") || $E.attr("resizer")
          		,	o = options[pane]
          		,	s = state[pane]
          		;
          		if (s.isClosed || s.isResizing)
          			return; // skip if already closed OR in process of resizing
          		else if (o.slideTrigger_close == "click")
          			close_NOW(); // close immediately onClick
          		else // trigger = mouseout - use a delay
          			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
          
          		// SUBROUTINE for timed close
          		function close_NOW () {
          			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
          			if (!s.isClosed) close(pane); // skip if already closed!
          		}
          	};
          
          
          	/**
          	 * sizePane
          	 *
          	 * @callers  initResizable.stop()
          	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
          	 * @param Integer  newSize  The new size for this pane - will be validated
          	 */
          	var sizePane = function (pane, size) {
          		// TODO: accept "auto" as size, and size-to-fit pane content
          		var 
          			edge	= c[pane].edge
          		,	dir		= c[pane].dir
          		,	o		= options[pane]
          		,	s		= state[pane]
          		,	$P		= $Ps[pane]
          		,	$R		= $Rs[pane]
          		;
          		// calculate 'current' min/max sizes
          		setPaneMinMaxSizes(pane); // update pane-state
          		// compare/update calculated min/max to user-options
          		s.minSize = max(s.minSize, o.minSize);
          		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
          		// validate passed size
          		size = max(size, s.minSize);
          		size = min(size, s.maxSize);
          		s.size = size; // update state
          
          		// move the resizer bar and resize the pane
          		$R.css( edge, size + cDims[edge] );
          		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
          
          		// resize all the adjacent panes, and adjust their toggler buttons
          		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
          		sizeHandles();
          		sizeContent(pane);
          		execUserCallback(pane, o.onresize_end || o.onresize);
          	};
          
          	/**
          	 * sizeMidPanes
          	 *
          	 * @callers  create(), open(), close(), onWindowResize()
          	 */
          	var sizeMidPanes = function (panes, overrideDims, onInit) {
          		if (!panes || panes == "all") panes = "east,west,center";
          
          		var d = getPaneDims();
          		if (overrideDims) $.extend( d, overrideDims );
          
          		$.each(panes.split(","), function() {
          			if (!$Ps[this]) return; // NO PANE - skip
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	hasRoom	= true
          			,	CSS		= {}
          			;
          
          			if (pane == "center") {
          				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
          				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
          				CSS.width  = max(1, cssW(pane, CSS.width));
          				CSS.height = max(1, cssH(pane, CSS.height));
          				hasRoom = (CSS.width > 1 && CSS.height > 1);
          				/*
          				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
          				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
          				 */
          				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
          					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
          					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
          				}
          			}
          			else { // for east and west, set only the height
          				CSS.top = d.top;
          				CSS.bottom = d.bottom;
          				CSS.height = max(1, cssH(pane, d.height));
          				hasRoom = (CSS.height > 1);
          			}
          
          			if (hasRoom) {
          				$P.css(CSS);
          				if (s.noRoom) {
          					s.noRoom = false;
          					if (s.isHidden) return;
          					else show(pane, !s.isClosed);
          					/* OLD CODE - keep until sure line above works right!
          					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
          					if ($R) $R.show();
          					*/
          				}
          				if (!onInit) {
          					sizeContent(pane);
          					execUserCallback(pane, o.onresize_end || o.onresize);
          				}
          			}
          			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
          				s.noRoom = true; // update state
          				if (s.isHidden) return;
          				if (onInit) { // skip onhide callback and other logic onLoad
          					$P.hide();
          					if ($R) $R.hide();
          				}
          				else hide(pane);
          			}
          		});
          	};
          
          
          	var sizeContent = function (panes) {
          		if (!panes || panes == "all") panes = c.allPanes;
          
          		$.each(panes.split(","), function() {
          			if (!$Cs[this]) return; // NO CONTENT - skip
          			var 
          				pane	= str(this)
          			,	ignore	= options[pane].contentIgnoreSelector
          			,	$P		= $Ps[pane]
          			,	$C		= $Cs[pane]
          			,	e_C		= $C[0]		// DOM element
          			,	height	= cssH($P);	// init to pane.innerHeight
          			;
          			$P.children().each(function() {
          				if (this == e_C) return; // Content elem - skip
          				var $E = $(this);
          				if (!ignore || !$E.is(ignore))
          					height -= $E.outerHeight();
          			});
          			if (height > 0)
          				height = cssH($C, height);
          			if (height < 1)
          				$C.hide(); // no room for content!
          			else
          				$C.css({ height: height }).show();
          		});
          	};
          
          
          	/**
          	 * sizeHandles
          	 *
          	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
          	 *
          	 * @callers  initHandles(), open(), close(), resizeAll()
          	 */
          	var sizeHandles = function (panes, onInit) {
          		if (!panes || panes == "all") panes = c.borderPanes;
          
          		$.each(panes.split(","), function() {
          			var 
          				pane	= str(this)
          			,	o		= options[pane]
          			,	s		= state[pane]
          			,	$P		= $Ps[pane]
          			,	$R		= $Rs[pane]
          			,	$T		= $Ts[pane]
          			;
          			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
          
          			var 
          				dir			= c[pane].dir
          			,	_state		= (s.isClosed ? "_closed" : "_open")
          			,	spacing		= o["spacing"+ _state]
          			,	togAlign	= o["togglerAlign"+ _state]
          			,	togLen		= o["togglerLength"+ _state]
          			,	paneLen
          			,	offset
          			,	CSS = {}
          			;
          			if (spacing == 0) {
          				$R.hide();
          				return;
          			}
          			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
          				$R.show(); // in case was previously hidden
          
          			// Resizer Bar is ALWAYS same width/height of pane it is attached to
          			if (dir == "horz") { // north/south
          				paneLen = $P.outerWidth();
          				$R.css({
          					width:	max(1, cssW($R, paneLen)) // account for borders & padding
          				,	height:	max(1, cssH($R, spacing)) // ditto
          				,	left:	cssNum($P, "left")
          				});
          			}
          			else { // east/west
          				paneLen = $P.outerHeight();
          				$R.css({
          					height:	max(1, cssH($R, paneLen)) // account for borders & padding
          				,	width:	max(1, cssW($R, spacing)) // ditto
          				,	top:	cDims.top + getPaneSize("north", true)
          				//,	top:	cssNum($Ps["center"], "top")
          				});
          				
          			}
          
          			if ($T) {
          				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
          					$T.hide(); // always HIDE the toggler when 'sliding'
          					return;
          				}
          				else
          					$T.show(); // in case was previously hidden
          
          				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
          					togLen = paneLen;
          					offset = 0;
          				}
          				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
          					if (typeof togAlign == "string") {
          						switch (togAlign) {
          							case "top":
          							case "left":	offset = 0;
          											break;
          							case "bottom":
          							case "right":	offset = paneLen - togLen;
          											break;
          							case "middle":
          							case "center":
          							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
          						}
          					}
          					else { // togAlign = number
          						var x = parseInt(togAlign); //
          						if (togAlign >= 0) offset = x;
          						else offset = paneLen - togLen + x; // NOTE: x is negative!
          					}
          				}
          
          				var
          					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
          				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
          				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
          				;
          				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
          				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
          
          				if (dir == "horz") { // north/south
          					var width = cssW($T, togLen);
          					$T.css({
          						width:	max(0, width)  // account for borders & padding
          					,	height:	max(1, cssH($T, spacing)) // ditto
          					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
          				}
          				else { // east/west
          					var height = cssH($T, togLen);
          					$T.css({
          						height:	max(0, height)  // account for borders & padding
          					,	width:	max(1, cssW($T, spacing)) // ditto
          					,	top:	offset // POSITION the toggler
          					});
          					if ($TC) // CENTER the toggler content SPAN
          						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
          				}
          
          
          			}
          
          			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
          			if (onInit && o.initHidden) {
          				$R.hide();
          				if ($T) $T.hide();
          			}
          		});
          	};
          
          
          	/**
          	 * resizeAll
          	 *
          	 * @callers  window.onresize(), callbacks or custom code
          	 */
          	var resizeAll = function () {
          		var
          			oldW	= cDims.innerWidth
          		,	oldH	= cDims.innerHeight
          		;
          		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
          
          		var
          			checkH	= (cDims.innerHeight < oldH)
          		,	checkW	= (cDims.innerWidth < oldW)
          		,	s, dir
          		;
          
          		if (checkH || checkW)
          			// NOTE special order for sizing: S-N-E-W
          			$.each(["south","north","east","west"], function(i,pane) {
          				s = state[pane];
          				dir = c[pane].dir;
          				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
          					setPaneMinMaxSizes(pane); // update pane-state
          					// shrink pane if 'too big' to fit
          					if (s.size > s.maxSize)
          						sizePane(pane, s.maxSize);
          				}
          			});
          
          		sizeMidPanes("all");
          		sizeHandles("all"); // reposition the toggler elements
          	};
          
          
          	/**
          	 * keyDown
          	 *
          	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
          	 *
          	 * @callers  document.keydown()
          	 */
          	function keyDown (evt) {
          		if (!evt) return true;
          		var code = evt.keyCode;
          		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
          
          		var
          			PANE = {
          				38: "north" // Up Cursor
          			,	40: "south" // Down Cursor
          			,	37: "west"  // Left Cursor
          			,	39: "east"  // Right Cursor
          			}
          		,	isCursorKey = (code >= 37 && code <= 40)
          		,	ALT = evt.altKey // no worky!
          		,	SHIFT = evt.shiftKey
          		,	CTRL = evt.ctrlKey
          		,	pane = false
          		,	s, o, k, m, el
          		;
          
          		if (!CTRL && !SHIFT)
          			return true; // no modifier key - abort
          		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
          			pane = PANE[code];
          		else // check to see if this matches a custom-hotkey
          			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
          				o = options[p];
          				k = o.customHotkey;
          				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
          				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
          					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
          						pane = p;
          						return false; // BREAK
          					}
          				}
          			});
          
          		if (!pane) return true; // no hotkey - abort
          
          		// validate pane
          		o = options[pane]; // get pane options
          		s = state[pane]; // get pane options
          		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
          
          		// see if user is in a 'form field' because may be 'selecting text'!
          		el = evt.target || evt.srcElement;
          		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
          			return true; // allow text-selection
          
          		// SYNTAX NOTES
          		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
          		// use "return false" to abort keystroke AND abort function
          		toggle(pane);
          		evt.stopPropagation();
          		evt.returnValue = false; // CANCEL key
          		return false;
          	};
          
          
          /*
           * ###########################
           *     UTILITY METHODS
           *   called externally only
           * ###########################
           */
          
          	function allowOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).attr("pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		;
          
          		// if pane is already raised, then reset it before doing it again!
          		// this would happen if allowOverflow is attached to BOTH the pane and an element 
          		if (s.cssSaved)
          			resetOverflow(pane); // reset previous CSS before continuing
          
          		// if pane is raised by sliding or resizing, or it's closed, then abort
          		if (s.isSliding || s.isResizing || s.isClosed) {
          			s.cssSaved = false;
          			return;
          		}
          
          		var
          			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
          		,	curCSS	= {}
          		,	of		= $P.css("overflow")
          		,	ofX		= $P.css("overflowX")
          		,	ofY		= $P.css("overflowY")
          		;
          		// determine which, if any, overflow settings need to be changed
          		if (of != "visible") {
          			curCSS.overflow = of;
          			newCSS.overflow = "visible";
          		}
          		if (ofX && ofX != "visible" && ofX != "auto") {
          			curCSS.overflowX = ofX;
          			newCSS.overflowX = "visible";
          		}
          		if (ofY && ofY != "visible" && ofY != "auto") {
          			curCSS.overflowY = ofX;
          			newCSS.overflowY = "visible";
          		}
          
          		// save the current overflow settings - even if blank!
          		s.cssSaved = curCSS;
          
          		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
          		$P.css( newCSS );
          
          		// make sure the zIndex of all other panes is normal
          		$.each(c.allPanes.split(","), function(i, p) {
          			if (p != pane) resetOverflow(p);
          		});
          
          	};
          
          	function resetOverflow (elem) {
          		if (this && this.tagName) elem = this; // BOUND to element
          		var $P;
          		if (typeof elem=="string")
          			$P = $Ps[elem];
          		else {
          			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
          			else $P = $(elem).parents("div[pane]:first");
          		}
          		if (!$P.length) return; // INVALID
          
          		var
          			pane	= $P.attr("pane")
          		,	s		= state[pane]
          		,	CSS		= s.cssSaved || {}
          		;
          		// reset the zIndex
          		if (!s.isSliding && !s.isResizing)
          			$P.css("zIndex", c.zIndex.pane_normal);
          
          		// reset Overflow - if necessary
          		$P.css( CSS );
          
          		// clear var
          		s.cssSaved = false;
          	};
          
          
          	/**
          	* getBtn
          	*
          	* Helper function to validate params received by addButton utilities
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
          	*/
          	function getBtn(selector, pane, action) {
          		var
          			$E = $(selector)
          		,	err = "Error Adding Button \n\nInvalid "
          		;
          		if (!$E.length) // element not found
          			alert(err+"selector: "+ selector);
          		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
          			alert(err+"pane: "+ pane);
          		else { // VALID
          			var btn = options[pane].buttonClass +"-"+ action;
          			$E.addClass( btn +" "+ btn +"-"+ pane );
          			return $E;
          		}
          		return false;  // INVALID
          	};
          
          
          	/**
          	* addToggleBtn
          	*
          	* Add a custom Toggler button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addToggleBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "toggle");
          		if ($E)
          			$E
          				.attr("title", state[pane].isClosed ? "Open" : "Close")
          				.click(function (evt) {
          					toggle(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addOpenBtn
          	*
          	* Add a custom Open button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addOpenBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "open");
          		if ($E)
          			$E
          				.attr("title", "Open")
          				.click(function (evt) {
          					open(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addCloseBtn
          	*
          	* Add a custom Close button for a pane
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
          	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
          	*/
          	function addCloseBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "close");
          		if ($E)
          			$E
          				.attr("title", "Close")
          				.click(function (evt) {
          					close(pane);
          					evt.stopPropagation();
          				})
          			;
          	};
          
          	/**
          	* addPinBtn
          	*
          	* Add a custom Pin button for a pane
          	*
          	* Four classes are added to the element, based on the paneClass for the associated pane...
          	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
          	*  - ui-layout-pane-pin
          	*  - ui-layout-pane-west-pin
          	*  - ui-layout-pane-pin-up
          	*  - ui-layout-pane-west-pin-up
          	*
          	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
          	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
          	*/
          	function addPinBtn (selector, pane) {
          		var $E = getBtn(selector, pane, "pin");
          		if ($E) {
          			var s = state[pane];
          			$E.click(function (evt) {
          				setPinState($(this), pane, (s.isSliding || s.isClosed));
          				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
          				else close( pane ); // slide-closed
          				evt.stopPropagation();
          			});
          			// add up/down pin attributes and classes
          			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
          			// add this pin to the pane data so we can 'sync it' automatically
          			// PANE.pins key is an array so we can store multiple pins for each pane
          			c[pane].pins.push( selector ); // just save the selector string
          		}
          	};
          
          	/**
          	* syncPinBtns
          	*
          	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
          	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
          	*
          	* @callers  open(), close()
          	* @params  pane   These are the params returned to callbacks by layout()
          	* @params  doPin  True means set the pin 'down', False means 'up'
          	*/
          	function syncPinBtns (pane, doPin) {
          		$.each(c[pane].pins, function (i, selector) {
          			setPinState($(selector), pane, doPin);
          		});
          	};
          
          	/**
          	* setPinState
          	*
          	* Change the class of the pin button to make it look 'up' or 'down'
          	*
          	* @callers  addPinBtn(), syncPinBtns()
          	* @param Element  $Pin		The pin-span element in a jQuery wrapper
          	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
          	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
          	*/
          	function setPinState ($Pin, pane, doPin) {
          		var updown = $Pin.attr("pin");
          		if (updown && doPin == (updown=="down")) return; // already in correct state
          		var
          			root	= options[pane].buttonClass
          		,	class1	= root +"-pin"
          		,	class2	= class1 +"-"+ pane
          		,	UP1		= class1 + "-up"
          		,	UP2		= class2 + "-up"
          		,	DN1		= class1 + "-down"
          		,	DN2		= class2 + "-down"
          		;
          		$Pin
          			.attr("pin", doPin ? "down" : "up") // logic
          			.attr("title", doPin ? "Un-Pin" : "Pin")
          			.removeClass( doPin ? UP1 : DN1 ) 
          			.removeClass( doPin ? UP2 : DN2 ) 
          			.addClass( doPin ? DN1 : UP1 ) 
          			.addClass( doPin ? DN2 : UP2 ) 
          		;
          	};
          
          
          /*
           * ###########################
           * CREATE/RETURN BORDER-LAYOUT
           * ###########################
           */
          
          	// init global vars
          	var 
          		$Container = $(this).css({ overflow: "hidden" }) // Container elem
          	,	$Ps		= {} // Panes x4	- set in initPanes()
          	,	$Cs		= {} // Content x4	- set in initPanes()
          	,	$Rs		= {} // Resizers x4	- set in initHandles()
          	,	$Ts		= {} // Togglers x4	- set in initHandles()
          	//	object aliases
          	,	c		= config // alias for config hash
          	,	cDims	= state.container // alias for easy access to 'container dimensions'
          	;
          
          	// create the border layout NOW
          	create();
          
          	// return object pointers to expose data & option Properties, and primary action Methods
          	return {
          		options:		options			// property - options hash
          	,	state:			state			// property - dimensions hash
          	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
          	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
          	,	open:			open			// method - ditto
          	,	close:			close			// method - ditto
          	,	hide:			hide			// method - ditto
          	,	show:			show			// method - ditto
          	,	resizeContent:	sizeContent		// method - ditto
          	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
          	,	resizeAll:		resizeAll		// method - no parameters
          	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
          	,	addOpenBtn:		addOpenBtn		// utility - ditto
          	,	addCloseBtn:	addCloseBtn		// utility - ditto
          	,	addPinBtn:		addPinBtn		// utility - ditto
          	,	allowOverflow:	allowOverflow	// utility - pass calling element
          	,	resetOverflow:	resetOverflow	// utility - ditto
          	,	cssWidth:		cssW
          	,	cssHeight:		cssH
          	};
          
          }
          })( jQuery );
          Evidence
          where
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        36. GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bFROM\b and was detected in the element starting with: "Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Mo", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (369 bytes)
          GET https://dev.duracloud.org/duradmin/js/thirdparty/date.js HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (451 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:55 GMT
          Content-Type: application/javascript
          Content-Length: 25809
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Accept-Ranges: bytes
          ETag: W/"25809-1571741506000"
          Last-Modified: Tue, 22 Oct 2019 10:51:46 GMT
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (25809 bytes)
          /**
           * Version: 1.0 Alpha-1 
           * Build Date: 13-Nov-2007
           * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
           * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
           * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
           */
          Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
          Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
          return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
          return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
          if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
          var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
          if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
          if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
          if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
          if(x.month||x.months){this.addMonths(x.month||x.months);}
          if(x.year||x.years){this.addYears(x.year||x.years);}
          if(x.day||x.days){this.addDays(x.day||x.days);}
          return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
          return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
          if(!x.second&&x.second!==0){x.second=-1;}
          if(!x.minute&&x.minute!==0){x.minute=-1;}
          if(!x.hour&&x.hour!==0){x.hour=-1;}
          if(!x.day&&x.day!==0){x.day=-1;}
          if(!x.month&&x.month!==0){x.month=-1;}
          if(!x.year&&x.year!==0){x.year=-1;}
          if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
          if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
          if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
          if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
          if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
          if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
          if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
          if(x.timezone){this.setTimezone(x.timezone);}
          if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
          return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
          var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
          return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
          Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
          return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
          var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
          return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
          var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
          return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
          (function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
          break;}
          return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
          return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
          throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
          return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
          if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){r=null;}
          if(r){return r;}}
          throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
          try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
          rx.push(r[0]);s=r[1];}
          return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
          return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
          rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
          s=q[1];}
          if(!r){throw new $P.Exception(s);}
          if(q){throw new $P.Exception(q[1]);}
          if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
          return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
          rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
          if(!last&&q[1].length===0){last=true;}
          if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
          p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
          if(rx[1].length<best[1].length){best=rx;}
          if(best[1].length===0){break;}}
          if(best[0].length===0){return best;}
          if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
          best[1]=q[1];}
          return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
          return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
          if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
          var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
          return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
          this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
          var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
          return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
          for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
          if(this.now){return new Date();}
          var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
          if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
          if(!this.unit){this.unit="day";}
          if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
          if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
          this[this.unit+"s"]=this.value*orient;}
          return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
          if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
          if(this.month&&!this.day){this.day=1;}
          return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
          fn=_C[keys]=_.any.apply(null,px);}
          return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
          return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
          return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
          try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
          return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
          
          Evidence
          from
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

        37. GET https://dev.duracloud.org/duradmin/spaces
          Alert tags
          Alert description

          The response appears to contain suspicious comments which may help an attacker. Note: Matches made within script blocks or files are against the entire content not only comments.

          Other info

          The following pattern was used: \bUSERNAME\b and was detected in the element starting with: "<script type="text/javascript">

          $(function() {

          $("#username").focus();

          $("#button-login").click(function(evt) {

          ", see evidence field for the suspicious comment/snippet.

          Request
          Request line and header section (354 bytes)
          GET https://dev.duracloud.org/duradmin/spaces HTTP/1.1
          Host: dev.duracloud.org
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
          Pragma: no-cache
          Cache-Control: no-cache
          Referer: https://dev.duracloud.org/duradmin/
          Cookie: JSESSIONID=BA85415E20038D7E9CFF1EA542ABFFFF
          
          
          Request body (0 bytes)
          Response
          Status line and header section (630 bytes)
          HTTP/1.1 200
          Date: Tue, 07 Dec 2021 17:15:54 GMT
          Content-Type: text/html;charset=UTF-8
          Content-Length: 7029
          Connection: keep-alive
          Server: Apache/2.4.46 () OpenSSL/1.0.2k-fips
          Cache-Control: no-cache, no-store, max-age=0, must-revalidate
          Pragma: no-cache
          Expires: 0
          Strict-Transport-Security: max-age=31536000 ; includeSubDomains
          X-XSS-Protection: 1; mode=block
          X-Frame-Options: SAMEORIGIN
          X-Content-Type-Options: nosniff
          Content-Language: en-US
          Vary: Accept-Encoding
          Access-Control-Allow-Origin: *
          Access-Control-Allow-Methods: GET, POST, PUT, DELETE
          Access-Control-Allow-Headers: Content-Type, Authorization
          
          
          Response body (7029 bytes)
          
          
          
          
          
          
          
          
          
          
          
          
          	
          
          	
          
          	
          <!DOCTYPE html>
          
          
          
          
          
          
          
          
          
          
          
          
          
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
          <!-- 
          	created by Daniel Bernstein and CH
           -->
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <meta name="language" content="en" />    
              <meta http-equiv="Expires" content="-1"/>
              
              <title>DuraCloud :: 
          		Login
          	</title>
          	<link rel="shortcut icon" href="/duradmin/favicon.ico" />
          	<link rel="stylesheet"  href="/duradmin/style/jquery-ui.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/base.css" type="text/css" />	
          	<link rel="stylesheet"  href="/duradmin/style/flex.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/dialogs.css" type="text/css" />
          	<link rel="stylesheet"  href="/duradmin/style/buttons.css" type="text/css" />
          
              <!-- non jquery third party plugins -->
              <script type="text/javascript" src="/duradmin/js/thirdparty/date.js"></script>
          
          	<!-- jquery core, ui and css -->
            
          	<script type="text/javascript" src="/duradmin/jquery/jquery.min.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/jquery-ui.js"></script>
          	<!-- 3rd party jquery plugins start-->
            <link type="text/css" rel="stylesheet" href="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.css" />
              <script type="text/javascript"
                  src="/duradmin/jquery/plugins/jquery.dropdown/jquery.dropdown.min.js"></script>
          
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.layout.js"></script>
          	<script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.ba-throttle-debounce.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery.form.min.js"></script>
              <script type="text/javascript"
          		src="/duradmin/jquery/plugins/jquery-validate/jquery.validate.js"></script>
          
              <link rel="stylesheet"
                href="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.css"
                type="text/css" media="screen" />
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.fancybox-1.3.1.js"></script>
              <script type="text/javascript"
                src="/duradmin/jquery/plugins/jquery.fancybox-1.3.1/fancybox/jquery.easing-1.3.pack.js"></script>
          
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.fn.ext.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/ext/jquery.dc.common.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.onoffswitch.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.selectablelist.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.listdetailviewer.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/widget/ui.expandopanel.js"></script>
          	<script type="text/javascript" src="/duradmin/jquery/dc/api/durastore-api.js"></script>
          
          	<script type="text/javascript">
          
          	$(function() {
          		
          		///////////////////////////////////////////////////////////////////////
          		////controls rollovers on tags and properties
          		///////////////////////////////////////////////////////////////////////
          		$(".dc-mouse-panel-activator td, li.dc-mouse-panel-activator, .dc-mouse-panel").live("mouseover",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","visible");
          		}).live("mouseout",function(evt){
          			var ancestor = $(evt.target).nearestOfClass(".dc-mouse-panel-activator");
          			$(".dc-mouse-panel",ancestor).css("visibility","hidden");
          		});
          		
          		$(".dc-mouse-panel").css("visibility", "hidden");
          		
          		///////////////////////////////////////////////////////////////////////
          		////Layout Page Frame
          		///////////////////////////////////////////////////////////////////////
          		var pageHeaderLayout;
          		 $("body").layout({
          				north__size:	    87
          			,   north__paneSelector:"#page-header"
          			,   resizable:   false
          			,   slidable:    false
          			,   spacing_open:			0			
          			,	togglerLength_open:		0			
          			,	togglerLength_closed:	-1
          			,	useStateCookie:		true
          			,   center__paneSelector: "#page-content"
          			,	center__onresize:	"centerLayout.resizeAll"
          			,   enableCursorHotkey: false
          		});
          	});	
          	</script>
          	<!-- page level header extensions reserved for pages that wish to inject page specific scripts into the header -->
          	
          		<link rel="stylesheet"  href="/duradmin/style/login.css" type="text/css" />
          	
          			
          </head>
          <body>
          	
          		<script type="text/javascript">
          		$(function() {
          			$("#username").focus();
          			$("#button-login").click(function(evt) {
          				evt.stopPropagation();
          				dc.login($("#loginForm"));
          			});
          		});
          		</script>
          
          		<form id="loginForm" action="/duradmin/login"  method="post" onsubmit="return false;" >
          			<div id="login-wrapper">
          				<div id="login-header" class="outer clearfix">
          					<div id="dc-logo-panel"><a href="/duradmin/spaces" id="dc-logo"><img src="/duradmin/images/logo_top_duracloud_lg.png" alt="DURACLOUD"/></a></div>
          				</div>
          				<div id="login-content" class="pane-L1-body clearfix">
          					<div id="form-fields" class="form-fields float-r">
          						<div id="msg-error" class="error" style="display:none">Username/Password combination not valid. Please try again.</div>
          
          						<ul>
          							<li class="clearfix">
          								<label for="username">Username</label>
          								<input type="text" id="username" name="username" class="field"/>
          							</li>
          							<li class="clearfix">
          								<label for="password">Password</label>
          								<input id="password" type="password" name="password" class="field"/>
          							</li>
          							<li class="clearfix">
          								<button id="button-login" class="primary  float-r">Login</button>
          								<span id="feedback" style="display:none; color:white" class="primary  float-r"><img src="/duradmin/images/wait.gif"/>Logging in...</span>
          
          							</li>
          						</ul>
          						<div id="login-links">
          						    <ul class="horizontal-list">
          							    <li><a href="https://ama-dev.duracloud.org/users/forgot-password" target="_blank">Forgot Password</a></li>
          						    </ul>
          						</div>
          					</div>
          				</div>
          
          				<div id="login-footer" class="outer footer clearfix">
          					<div class="footer-content">
          						<div class="float-r" id="logo-ds"></div>
          DuraCloud Administrator v7.1.0-SNAPSHOT rev:a328d <span class="sep">|</span>
          &copy;<script type="text/javascript">document.write(new Date().getFullYear());</script>
          
          
          
          <a target="_blank" href="http://duracloud.org">DuraCloud</a>  <span class="sep">|</span>
          <a target="_blank" href="http://lyrasis.org">LYRASIS</a>  <span class="sep">|</span>
          
          
          <a target="_blank" href="https://wiki.lyrasis.org/display/DURACLOUD/DuraCloud+Help+Center">Help Center</a> <span class="sep">|</span>
          <a target="_blank" href="https://lyrasis.zendesk.com/">Support</a>
          
          					</div>
          				</div>
          			</div>
          		</form>
          	
              
          </body>
          </html>
          
          
          Evidence
          username
          Solution

          Remove all comments that return information that may help an attacker and fix any underlying problems they refer to.

Appendix

Alert types

This section contains additional information on the types of alerts in the report.

  1. Cross-Domain Misconfiguration

    Source raised by a passive scanner (Cross-Domain Misconfiguration)
    CWE ID 264
    WASC ID 14
    Reference
    1. https://vulncat.fortify.com/en/detail?id=desc.config.dotnet.html5_overly_permissive_cors_policy
  2. Vulnerable JS Library

    Source raised by a passive scanner (Vulnerable JS Library)
    CWE ID 829
    Reference
    1. https://nvd.nist.gov/vuln/detail/CVE-2012-6708
    2. https://github.com/jquery/jquery/issues/2432
    3. http://research.insecurelabs.org/jquery/test/
    4. http://blog.jquery.com/2016/01/08/jquery-2-2-and-1-12-released/
    5. http://bugs.jquery.com/ticket/11290
    6. https://blog.jquery.com/2019/04/10/jquery-3-4-0-released/
    7. https://nvd.nist.gov/vuln/detail/CVE-2019-11358
    8. https://nvd.nist.gov/vuln/detail/CVE-2015-9251
    9. https://github.com/jquery/jquery/commit/753d591aea698e57d6db58c9f722cd0808619b1b
    10. https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/
  3. Absence of Anti-CSRF Tokens

    Source raised by a passive scanner (Absence of Anti-CSRF Tokens)
    CWE ID 352
    WASC ID 9
    Reference
    1. http://projects.webappsec.org/Cross-Site-Request-Forgery
    2. http://cwe.mitre.org/data/definitions/352.html
  4. Cookie without SameSite Attribute

    Source raised by a passive scanner (Cookie without SameSite Attribute)
    CWE ID 1275
    WASC ID 13
    Reference
    1. https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site
  5. Timestamp Disclosure - Unix

    Source raised by a passive scanner (Timestamp Disclosure)
    CWE ID 200
    WASC ID 13
    Reference
    1. http://projects.webappsec.org/w/page/13246936/Information%20Leakage
  6. X-Content-Type-Options Header Missing

    Source raised by a passive scanner (X-Content-Type-Options Header Missing)
    CWE ID 693
    WASC ID 15
    Reference
    1. http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx
    2. https://owasp.org/www-community/Security_Headers
  7. Information Disclosure - Suspicious Comments

    Source raised by a passive scanner (Information Disclosure - Suspicious Comments)
    CWE ID 200
    WASC ID 13